Merge pull request #26617 from huan086/lingui__react

@lingui/react: Add Typescript definitions
This commit is contained in:
Nathan Shively-Sanders
2018-06-19 13:03:17 -07:00
committed by GitHub
17 changed files with 469 additions and 0 deletions
+2
View File
@@ -0,0 +1,2 @@
export function date(language: string, format?: Intl.DateTimeFormatOptions): (value: Date) => string;
export function number(language: string, format?: Intl.NumberFormatOptions): (value: number) => string;
+69
View File
@@ -0,0 +1,69 @@
import { SelectProps, PluralProps } from "./select";
// In flowtype, MessageOptions is declared as exact type
export interface MessageOptions {
defaults?: string;
formats?: object;
}
export interface LanguageData {
plurals?: (n: number, pluralType?: "cardinal" | "ordinal") => string;
}
export interface Messages {
[key: string]: string | ((context: (name: string, type?: string, format?: any) => string) => (string | string[]));
}
export interface Catalog {
messages: Messages;
languageData?: LanguageData;
}
export interface Catalogs {
[key: string]: Catalog;
}
export interface setupI18nProps {
language?: string;
catalogs?: Catalogs;
development?: object;
}
export class I18n {
t(strings: TemplateStringsArray, ...values: any[]): string;
t(id: string): (strings: TemplateStringsArray, ...values: any[]) => string;
select(config: SelectProps): string;
select(id: string, config: SelectProps): string;
plural(config: PluralProps): string;
plural(id: string, config: PluralProps): string;
selectOrdinal(config: PluralProps): string;
selectOrdinal(id: string, config: PluralProps): string;
constructor();
availableLanguages: string[];
language: string;
messages: Messages;
languageData: LanguageData;
load(catalogs: Catalogs): void;
activate(language: string): void;
use(language: string): I18n;
_(id: string, values?: object, messageOptions?: MessageOptions): string;
pluralForm(n: number, pluralType?: "cardinal" | "ordinal"): string;
}
export function setupI18n(params?: setupI18nProps): I18n;
export const i18n: I18n;
+21
View File
@@ -0,0 +1,21 @@
// Type definitions for @lingui/core 2.1
// Project: https://lingui.github.io/js-lingui/
// Definitions by: Jeow Li Huan <https://github.com/huan086>
// Definitions: https://github.com/huan086/lingui-typings
export {
i18n,
setupI18n,
Catalog,
Catalogs,
MessageOptions,
LanguageData,
I18n
} from './i18n';
export {
date,
number
} from './formats';
export function i18nMark(id: string): string;
+89
View File
@@ -0,0 +1,89 @@
import {
i18n,
setupI18n,
Catalog,
Catalogs,
MessageOptions,
LanguageData,
I18n,
date,
number,
i18nMark
} from '@lingui/core';
const age = 12;
const templateResult: string = i18n.t`${age} years old`;
const templateIdResult: string = i18n.t('templateId')`${age} years old`;
const translateResult: string = i18n._('age', { age }, { defaults: '{age} years old' });
const count = 42;
const pluralResult: string = i18n.plural({
value: count,
0: 'no books',
one: '# book',
other: '# books'
});
const pluralIdResult: string = i18n.plural('pluralId', {
value: count,
0: 'no books',
one: '# book',
other: '# books'
});
const selectOrdinalResult: string = i18n.selectOrdinal({
value: count,
0: 'Zeroth book',
one: '#st book',
two: '#nd book',
few: '#rd book',
other: '#th book'
});
const selectOrdinalIdResult: string = i18n.selectOrdinal('selectOrdinalId', {
value: count,
0: 'Zeroth book',
one: '#st book',
two: '#nd book',
few: '#rd book',
other: '#th book'
});
const gender = 'female';
const numOfGuests = 2;
const host = 'Amy';
const guest = 'Bob';
const selectResult = i18n.select({
value: gender,
female: i18n.plural({
value: numOfGuests,
offset: 1,
0: i18n.t`${host} does not give a party.`,
1: i18n.t`${host} invites ${guest} to her party.`,
2: i18n.t`${host} invites ${guest} and one other person to her party.`,
other: i18n.t`${host} invites ${guest} and # other people to her party.`
}),
male: 'male',
other: 'other'
});
const selectIdResult = i18n.select('selectId', {
value: gender,
female: 'female',
male: 'male',
other: 'other'
});
const catalog: Catalog = {
messages: {
age(a) {
return [a('age'), 'años de edad'];
}
}
};
const catalogs: Catalogs = { es: catalog };
const setupResult: I18n = setupI18n({ catalogs, language: 'es' });
const formattedDate: string = date('en', { timeZone: 'UTC' })(new Date());
const formattedNumber: string = number('en', { style: 'currency', currency: 'EUR' })(1234.56);
const mark: string = i18nMark('mark');
+20
View File
@@ -0,0 +1,20 @@
export interface PluralForms {
zero?: string;
one?: string;
two?: string;
few?: string;
many?: string;
other: string;
[exact: number]: string;
}
export interface PluralProps extends PluralForms {
value: number;
offset?: number;
}
export interface SelectProps {
value: string;
other: string;
[selectForm: string]: string;
}
+28
View File
@@ -0,0 +1,28 @@
{
"compilerOptions": {
"module": "commonjs",
"lib": [
"es6"
],
"noImplicitAny": true,
"noImplicitThis": true,
"strictNullChecks": true,
"strictFunctionTypes": true,
"baseUrl": "../",
"typeRoots": [
"../"
],
"types": [],
"noEmit": true,
"forceConsistentCasingInFileNames": true,
"paths": {
"@lingui/core": [
"lingui__core"
]
}
},
"files": [
"index.d.ts",
"lingui__core-tests.ts"
]
}
+1
View File
@@ -0,0 +1 @@
{ "extends": "dtslint/dt.json" }
+14
View File
@@ -0,0 +1,14 @@
import { Component, ReactNode } from 'react';
import { I18n, Catalogs } from '@lingui/core';
// tslint:disable-next-line:interface-name
export interface I18nProviderProps {
children?: ReactNode;
language: string;
catalogs?: Catalogs;
i18n?: I18n;
defaultRender?: ReactNode;
}
export default class I18nProvider extends Component<I18nProviderProps> { }
+6
View File
@@ -0,0 +1,6 @@
import { ReactNode } from 'react';
export interface RenderProps {
render?: ReactNode;
className?: string;
}
+26
View File
@@ -0,0 +1,26 @@
import { Component, ReactNode } from 'react';
import { RenderProps } from './Render';
export interface PluralPropsWithoutI18n extends RenderProps {
id?: string;
value: number | string;
offset?: number | string;
zero?: ReactNode;
one?: ReactNode;
two?: ReactNode;
few?: ReactNode;
many?: ReactNode;
other: ReactNode;
[exact: string]: ReactNode;
}
export interface SelectPropsWithoutI18n extends RenderProps {
id?: string;
value: string;
other: ReactNode;
[exact: string]: ReactNode;
}
export class Select extends Component<SelectPropsWithoutI18n> { }
export class Plural extends Component<PluralPropsWithoutI18n> { }
export class SelectOrdinal extends Component<PluralPropsWithoutI18n> { }
+13
View File
@@ -0,0 +1,13 @@
import { Component, ReactElement, ReactNode } from 'react';
import { RenderProps } from './Render';
export interface TransPropsWithoutI18n extends RenderProps {
id?: string;
defaults?: string;
values?: object;
formats?: object;
components?: ReadonlyArray<ReactElement<any>>;
children?: ReactNode;
}
export default class Trans extends Component<TransPropsWithoutI18n> { }
+6
View File
@@ -0,0 +1,6 @@
import { RenderProps } from './Render';
export interface FormatPropsWithoutI18n<V, FormatOptions> extends RenderProps {
value: V;
format?: FormatOptions;
}
+20
View File
@@ -0,0 +1,20 @@
// Type definitions for @lingui/react 2.1
// Project: https://lingui.github.io/js-lingui/
// Definitions by: Jeow Li Huan <https://github.com/huan086>
// Definitions: https://github.com/huan086/lingui-typings
// TypeScript Version: 2.8
import { ComponentClass } from 'react';
import { FormatPropsWithoutI18n } from './createFormat';
export { default as withI18n, withI18nProps } from './withI18n';
export { default as I18nProvider } from './I18nProvider';
export { default as Trans } from './Trans';
export { Plural, Select, SelectOrdinal } from './Select';
export const DateFormat: ComponentClass<FormatPropsWithoutI18n<Date, Intl.DateTimeFormatOptions>>;
export const NumberFormat: ComponentClass<FormatPropsWithoutI18n<number, Intl.NumberFormatOptions>>;
export function i18nMark(id: string): string;
+102
View File
@@ -0,0 +1,102 @@
import * as React from 'react';
import { Catalog, Catalogs, I18n } from '@lingui/core';
import {
withI18n,
I18nProvider,
Trans,
Plural,
Select,
SelectOrdinal,
DateFormat,
NumberFormat,
i18nMark
} from '@lingui/react';
const catalog: Catalog = {
messages: {
ageId(a) {
return [a('age'), 'años de edad'];
}
}
};
const catalogs: Catalogs = { es: catalog };
interface LocalizeAttributeBaseProps {
i18n: I18n;
age: number;
}
const LocalizeAttributeBase = (props: LocalizeAttributeBaseProps) => {
const { i18n, age } = props;
return (
<span title={i18n.t`Age: ${age}`} aria-label={i18n.t('ageId')`${age} years old`}>Attributes</span>
);
};
const LocalizeAttribute = withI18n()(LocalizeAttributeBase);
const LocalizeOptionAttribute = withI18n({ update: true, withRef: true, withHash: true })(LocalizeAttributeBase);
const App = () => {
const name = 'Ken';
const numBooks = 58;
const gender = 'male';
const price = 21.35;
const lastLogin = new Date();
return (
<I18nProvider language="es" catalogs={catalogs}>
<LocalizeAttribute age={23} />
<LocalizeOptionAttribute age={23} />
<Trans>Name {name} in <code>Trans</code>.</Trans>
<Trans id="transId">Name {name} in <code>Trans</code> with <code>id</code>.</Trans>
<Plural id="msg.plural"
value={numBooks}
_0={<Trans>{name} has no books</Trans>}
one={<Trans>{name} has # book</Trans>}
other={<Trans>{name} has # books</Trans>}
_999999="Just a string"
/>
<Plural value={numBooks}
_0={<Trans>{name} has no books</Trans>}
one={<Trans>{name} has # book</Trans>}
other={<Trans>{name} has # books</Trans>}
_999999="Just a string"
/>
<Select id="msg.select"
value={gender}
male={<Trans>{name} and his friends</Trans>}
female={<Trans>{name} and her friends</Trans>}
other={<Trans>{name} and their friends</Trans>}
_999999="Just a string"
/>
<Select value={gender}
male={<Trans>{name} and his friends</Trans>}
female={<Trans>{name} and her friends</Trans>}
other={<Trans>{name} and their friends</Trans>}
_999999="Just a string"
/>
<SelectOrdinal id="msg.selectOrdinal"
value={numBooks}
_0={<Trans>No books from {name}</Trans>}
one={<Trans>#st book from {name}</Trans>}
two={<Trans>#nd book from {name}</Trans>}
other={<Trans>#th book from {name}</Trans>}
_999999="Just a string"
/>
<SelectOrdinal value={numBooks}
_0={<Trans>No books from {name}</Trans>}
one={<Trans>#st book from {name}</Trans>}
two={<Trans>#nd book from {name}</Trans>}
other={<Trans>#th book from {name}</Trans>}
_999999="Just a string"
/>
<Trans>Last login on <DateFormat format={{ timeZone: 'UTC' }} value={lastLogin} />.</Trans>
<Trans>
Price of book: <NumberFormat
format={{ style: 'currency', currency: 'EUR', minimumFractionDigits: 2 }}
value={price} />.
</Trans>
</I18nProvider>
);
};
const mark: string = i18nMark('mark');
+33
View File
@@ -0,0 +1,33 @@
{
"compilerOptions": {
"module": "commonjs",
"lib": [
"es6",
"dom"
],
"noImplicitAny": true,
"noImplicitThis": true,
"strictNullChecks": true,
"strictFunctionTypes": true,
"baseUrl": "../",
"jsx": "react",
"typeRoots": [
"../"
],
"types": [],
"noEmit": true,
"forceConsistentCasingInFileNames": true,
"paths": {
"@lingui/core": [
"lingui__core"
],
"@lingui/react": [
"lingui__react"
]
}
},
"files": [
"index.d.ts",
"lingui__react-tests.tsx"
]
}
+1
View File
@@ -0,0 +1 @@
{ "extends": "dtslint/dt.json" }
+18
View File
@@ -0,0 +1,18 @@
import { ComponentClass, StatelessComponent } from 'react';
import { I18n } from '@lingui/core';
import { withI18nProps } from './withI18n';
export type ComponentConstructor<P> = ComponentClass<P> | StatelessComponent<P>;
export interface withI18nOptions {
update?: boolean;
withRef?: boolean;
withHash?: boolean;
}
export interface withI18nProps {
i18n: I18n;
}
export default function withI18n(options?: withI18nOptions):
<P>(WrappedComponent: ComponentConstructor<P>) => ComponentClass<Pick<P, Exclude<keyof P, keyof withI18nProps>>>;