diff --git a/types/lingui__core/formats.d.ts b/types/lingui__core/formats.d.ts new file mode 100644 index 0000000000..841f6404e8 --- /dev/null +++ b/types/lingui__core/formats.d.ts @@ -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; diff --git a/types/lingui__core/i18n.d.ts b/types/lingui__core/i18n.d.ts new file mode 100644 index 0000000000..49f663a6a8 --- /dev/null +++ b/types/lingui__core/i18n.d.ts @@ -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; diff --git a/types/lingui__core/index.d.ts b/types/lingui__core/index.d.ts new file mode 100644 index 0000000000..c0aa933bee --- /dev/null +++ b/types/lingui__core/index.d.ts @@ -0,0 +1,21 @@ +// Type definitions for @lingui/core 2.1 +// Project: https://lingui.github.io/js-lingui/ +// Definitions by: Jeow Li Huan +// 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; diff --git a/types/lingui__core/lingui__core-tests.ts b/types/lingui__core/lingui__core-tests.ts new file mode 100644 index 0000000000..799bc5812b --- /dev/null +++ b/types/lingui__core/lingui__core-tests.ts @@ -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'); diff --git a/types/lingui__core/select.d.ts b/types/lingui__core/select.d.ts new file mode 100644 index 0000000000..6a2eb51db9 --- /dev/null +++ b/types/lingui__core/select.d.ts @@ -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; +} diff --git a/types/lingui__core/tsconfig.json b/types/lingui__core/tsconfig.json new file mode 100644 index 0000000000..e01d974c46 --- /dev/null +++ b/types/lingui__core/tsconfig.json @@ -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" + ] +} diff --git a/types/lingui__core/tslint.json b/types/lingui__core/tslint.json new file mode 100644 index 0000000000..3db14f85ea --- /dev/null +++ b/types/lingui__core/tslint.json @@ -0,0 +1 @@ +{ "extends": "dtslint/dt.json" } diff --git a/types/lingui__react/I18nProvider.d.ts b/types/lingui__react/I18nProvider.d.ts new file mode 100644 index 0000000000..9eb0158fac --- /dev/null +++ b/types/lingui__react/I18nProvider.d.ts @@ -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 { } diff --git a/types/lingui__react/Render.d.ts b/types/lingui__react/Render.d.ts new file mode 100644 index 0000000000..d9ccf003c0 --- /dev/null +++ b/types/lingui__react/Render.d.ts @@ -0,0 +1,6 @@ +import { ReactNode } from 'react'; + +export interface RenderProps { + render?: ReactNode; + className?: string; +} diff --git a/types/lingui__react/Select.d.ts b/types/lingui__react/Select.d.ts new file mode 100644 index 0000000000..044d4bf473 --- /dev/null +++ b/types/lingui__react/Select.d.ts @@ -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 { } +export class Plural extends Component { } +export class SelectOrdinal extends Component { } diff --git a/types/lingui__react/Trans.d.ts b/types/lingui__react/Trans.d.ts new file mode 100644 index 0000000000..c1834b770d --- /dev/null +++ b/types/lingui__react/Trans.d.ts @@ -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>; + children?: ReactNode; +} + +export default class Trans extends Component { } diff --git a/types/lingui__react/createFormat.d.ts b/types/lingui__react/createFormat.d.ts new file mode 100644 index 0000000000..49bebb079e --- /dev/null +++ b/types/lingui__react/createFormat.d.ts @@ -0,0 +1,6 @@ +import { RenderProps } from './Render'; + +export interface FormatPropsWithoutI18n extends RenderProps { + value: V; + format?: FormatOptions; +} diff --git a/types/lingui__react/index.d.ts b/types/lingui__react/index.d.ts new file mode 100644 index 0000000000..1fbe1e5c05 --- /dev/null +++ b/types/lingui__react/index.d.ts @@ -0,0 +1,20 @@ +// Type definitions for @lingui/react 2.1 +// Project: https://lingui.github.io/js-lingui/ +// Definitions by: Jeow Li Huan +// 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>; +export const NumberFormat: ComponentClass>; + +export function i18nMark(id: string): string; diff --git a/types/lingui__react/lingui__react-tests.tsx b/types/lingui__react/lingui__react-tests.tsx new file mode 100644 index 0000000000..3fc8cebebb --- /dev/null +++ b/types/lingui__react/lingui__react-tests.tsx @@ -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 ( + Attributes + ); +}; + +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 ( + + + + Name {name} in Trans. + Name {name} in Trans with id. + {name} has no books} + one={{name} has # book} + other={{name} has # books} + _999999="Just a string" + /> + {name} has no books} + one={{name} has # book} + other={{name} has # books} + _999999="Just a string" + /> + {name} and his friends} + female={{name} and her friends} + other={{name} and their friends} + _999999="Just a string" + /> + No books from {name}} + one={#st book from {name}} + two={#nd book from {name}} + other={#th book from {name}} + _999999="Just a string" + /> + No books from {name}} + one={#st book from {name}} + two={#nd book from {name}} + other={#th book from {name}} + _999999="Just a string" + /> + Last login on . + + Price of book: . + + + ); +}; + +const mark: string = i18nMark('mark'); diff --git a/types/lingui__react/tsconfig.json b/types/lingui__react/tsconfig.json new file mode 100644 index 0000000000..3b53ee659c --- /dev/null +++ b/types/lingui__react/tsconfig.json @@ -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" + ] +} diff --git a/types/lingui__react/tslint.json b/types/lingui__react/tslint.json new file mode 100644 index 0000000000..3db14f85ea --- /dev/null +++ b/types/lingui__react/tslint.json @@ -0,0 +1 @@ +{ "extends": "dtslint/dt.json" } diff --git a/types/lingui__react/withI18n.d.ts b/types/lingui__react/withI18n.d.ts new file mode 100644 index 0000000000..00595ee2d5 --- /dev/null +++ b/types/lingui__react/withI18n.d.ts @@ -0,0 +1,18 @@ +import { ComponentClass, StatelessComponent } from 'react'; +import { I18n } from '@lingui/core'; +import { withI18nProps } from './withI18n'; + +export type ComponentConstructor

= ComponentClass

| StatelessComponent

; + +export interface withI18nOptions { + update?: boolean; + withRef?: boolean; + withHash?: boolean; +} + +export interface withI18nProps { + i18n: I18n; +} + +export default function withI18n(options?: withI18nOptions): +

(WrappedComponent: ComponentConstructor

) => ComponentClass>>;