diff --git a/.gitignore b/.gitignore index ee1bb96..191e7e4 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,5 @@ node_modules *.log dist/ -coverage/ \ No newline at end of file +coverage/ +docs/ \ No newline at end of file diff --git a/.gitmodules b/.gitmodules deleted file mode 100644 index 5d76993..0000000 --- a/.gitmodules +++ /dev/null @@ -1,3 +0,0 @@ -[submodule "docs"] - path = docs - url = git@github.com:kaisermann/svelte-i18n.wiki.git diff --git a/.nvmrc b/.nvmrc new file mode 100644 index 0000000..154afe1 --- /dev/null +++ b/.nvmrc @@ -0,0 +1 @@ +11.15.0 \ No newline at end of file diff --git a/README.md b/README.md index 72db4a2..52979a3 100644 --- a/README.md +++ b/README.md @@ -1,333 +1,9 @@ +> **WIP document** + # svelte-i18n > Internationalization for Svelte. - - - - - - -- [TODO - WIP](#todo-wip) -- [Usage](#usage) - - [Locale](#locale) - - [The dictionary](#the-dictionary) - - [Formatting](#formatting) - - [Formatting methods](#formatting-methods) - - [Formats](#formats) -- [CLI](#cli) - - [Options](#options) - - - -## TODO - WIP - -- [x] Maybe locale can be a promise so we can await for it on the template; -- [ ] Wiki on github; -- [x] Find a more flexible way to preload dictionaries so it's possible to preload partial dictionaries. - -## Usage - `svelte-i18n` uses `stores` to keep track of the current locale, dictionary of messages and the main format function. This way, we keep everything neat, in sync and easy to use on your svelte files. ---- - -### Locale - -The `locale` store defines what is the current locale. - -```js -import { locale, dictionary, getClientLocale } from 'svelte-i18n' - -// Set the current locale to en-US -locale.set('en-US') - -// This is a store, so we can subscribe to its changes -locale.subscribe(() => console.log('locale change')) - -// svelte-i18n exports a method to help getting the current client locale -locale.set( - getClientLocale({ - // the fallback locale, if didn't find any - fallback: 'en-US', - // set to 'true' to check the 'window.navigator.language' - navigator: true, - // set the key name to look for a locale on 'window.location.search' - // 'example.com?locale=en-US' - search: 'lang', - // set the key name to look for a locale on 'window.location.hash' - // 'example.com#locale=en-US' - hash: 'locale', - // define a pattern to look in the window.location.pathname. It returns the first capturing group. - pathname: /^\/(.*?)\//, - // define a pattern to look in the window.location.hostname. It returns the first capturing group. - hostname: /^\/(.*?)\//, - }) -) -``` - -If a locale with the format `xx-YY` is not found, `svelte-i18n` looks for the locale `xx` as well. - ---- - -### The dictionary - -The `dictionary` store defines the dictionary of messages of all locales. - -```js -import { locale, dictionary } from 'svelte-i18n' - -// Define a locale dictionary -dictionary.set({ - pt: { - message: 'Mensagem', - 'switch.lang': 'Trocar idioma', - greeting: { - ask: 'Por favor, digite seu nome', - message: 'Olá {name}, como vai?', - }, - photos: - 'Você {n, plural, =0 {não tem fotos.} =1 {tem uma foto.} other {tem # fotos.}}', - cats: 'Tenho {n, number} {n,plural,=0{gatos}one{gato}other{gatos}}', - }, - en: { - message: 'Message', - 'switch.lang': 'Switch language', - greeting: { - ask: 'Please type your name', - message: 'Hello {name}, how are you?', - }, - photos: - 'You have {n, plural, =0 {no photos.} =1 {one photo.} other {# photos.}}', - cats: 'I have {n, number} {n,plural,one{cat}other{cats}}', - }, -}) - -// It's also possible to merge the current dictionary -// with other objets -dictionary.update(dict => { - dict.fr = { - // ...french messages - } - return dict -}) -``` - -Each language message dictionary can be as deep as you want. Messages can also be looked up by a string represetation of it's path on the dictionary (i.e `greeting.message`). - ---- - -### Formatting - -The `_`/`format` store is the actual formatter method. To use it it's simple as any other svelte store. - -```html - - - -``` - -`svelte-i18n` uses `formatjs` behind the scenes, which means it supports the [ICU message format](http://userguide.icu-project.org/formatparse/messages) for interpolation, pluralization and much more. - -```html -
- {$_('greeting.message', { values: { name: 'John' }})} - - - {$_('photos', { values: { n: 0 }})} - - - {$_('photos', { values: { n: 12} })} - -
-``` - -### Formatting methods - -#### `_` / `format` - -Main formatting method that formats a localized message by its `id`. - -```ts -function(messageId: string, options?: MessageObject): string -function(options: MessageObject): string - -interface MessageObject { - id?: string - locale?: string - format?: string - default?: string - values?: Record -} -``` - -- `id`: represents the path to a specific message; -- `locale`: forces a specific locale; -- `default`: the default value in case of message not found in the current locale; -- `format`: the format to be used. See [#formats](#formats); -- `values`: properties that should be interpolated in the message; - -You can pass a `string` as the first parameter for a less verbose way of formatting a message. - -```html - - -
{$_('greeting.ask')}
- - -
{$_({ id: 'greeting.ask' })}
- -``` - -The formatter method also provides some casing utilities: - -- `_.upper` - transforms a localized message into uppercase; -- `_.lower` - transforms a localized message into lowercase; -- `_.capital` - capitalize a localized message; -- `_.title` - transforms the message into title case; - -```html -
{$_.upper('greeting.ask')}
- - -
{$_.lower('greeting.ask')}
- - -
{$_.capital('greeting.ask')}
- - -
{$_.title('greeting.ask')}
- -``` - -#### `_.time` - -Formats a date object into a time string with the specified format (`short`, `medium`, `long`, `full`). Please refer to the [#formats](#formats) section to see available formats. - -```ts -function(time: Date, options: MessageObject): string -``` - -```html -
{$_.time(new Date(2019, 3, 24, 23, 45))}
- - -
{$_.time(new Date(2019, 3, 24, 23, 45), { format: 'medium' } )}
- -``` - -#### `_.date` - -Formats a date object into a string with the specified format (`short`, `medium`, `long`, `full`). Please refer to the [#formats](#formats) section to see available formats. - -```ts -function(date: Date, options: MessageObject): string -``` - -```html -
{$_.date(new Date(2019, 3, 24, 23, 45))}
- - -
{$_.date(new Date(2019, 3, 24, 23, 45), { format: 'medium' } )}
- -``` - -#### `_.number` - -Formats a number with the specified locale and format. Please refer to the [#formats](#formats) section to see available formats. - -```ts -function(number: number, options: MessageObject): string -``` - -```html -
{$_.number(100000000)}
- - -
{$_.number(100000000, { locale: 'pt' })}
- -``` - -### Formats - -`svelte-i18n` comes with a set of default `number`, `time` and `date` formats: - -**Number:** - -- `currency`: `{ style: 'currency' }` -- `percent`: `{ style: 'percent' }` -- `scientific`: `{ notation: 'scientific' }` -- `engineering`: `{ notation: 'engineering' }` -- `compactLong`: `{ notation: 'compact', compactDisplay: 'long' }` -- `compactShort`: `{ notation: 'compact', compactDisplay: 'short' }` - -**Date:** - -- `short`: `{ month: 'numeric', day: 'numeric', year: '2-digit' }` -- `medium`: `{ month: 'short', day: 'numeric', year: 'numeric' }` -- `long`: `{ month: 'long', day: 'numeric', year: 'numeric' }` -- `full`: `{ weekday: 'long', month: 'long', day: 'numeric', year: 'numeric' }` - -**Time:** - -- `short`: `{ hour: 'numeric', minute: 'numeric' }` -- `medium`: `{ hour: 'numeric', minute: 'numeric', second: 'numeric' }` -- `long`: `{ hour: 'numeric', minute: 'numeric', second: 'numeric', timeZoneName: 'short' }` -- `full`: `{ hour: 'numeric', minute: 'numeric', second: 'numeric', timeZoneName: 'short' }` - -It's possible to define custom format styles via the `addCustomFormats` method if you need to supply a set of options to the underlying `Intl` formatter. - -```ts -function addCustomFormats(formatsObject: Formats): void - -interface Formats { - number: Record - date: Record - time: Record -} -``` - -Please refer to the [Intl.NumberFormat](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/NumberFormat) and [Intl.DateTimeFormat](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/DateTimeFormat) documentations to see available formatting options. - -**Example**: - -```js -import { addCustomFormats } from 'svelte-i18n' - -addCustomFormats({ - number: { - EUR: { - style: 'currency', - currency: 'EUR', - }, - }, -}) -``` - -```html -
- {$_.number(123456.789, { format: 'EUR' })} -
- -``` - -## CLI - -`svelte-i18n` provides a command-line interface to extract all your messages to the `stdout` or to a specific JSON file. - -```bash -$ svelte-i18n extract [options] [output-file] -``` - -### Options - -- `-s, --shallow` - extract all messages to a shallow object, without creating nested objects. Default: `false`. - -- `--overwrite` - overwrite the content of the `output` file instead of just appending missing properties. Default: `false`. - -- `-c, --configDir` - define the directory of a [`svelte.config.js`](https://github.com/UnwrittenFun/svelte-vscode#generic-setup) in case your svelte components need to be preprocessed. +### [Go to documentation](https://github.com/kaisermann/svelte-i18n/wiki) diff --git a/docs b/docs deleted file mode 160000 index acadff6..0000000 --- a/docs +++ /dev/null @@ -1 +0,0 @@ -Subproject commit acadff6027a315e011a7157ae3b139d5e4cc3ae5 diff --git a/example/package.json b/example/package.json index 54c41c7..9b9b85d 100644 --- a/example/package.json +++ b/example/package.json @@ -14,7 +14,6 @@ "dependencies": { "compression": "^1.7.1", "polka": "next", - "rollup-plugin-json": "^4.0.0", "sirv": "^0.4.0", "svelte-i18n": "^2.0.0-alpha.2" }, @@ -24,6 +23,7 @@ "@babel/plugin-transform-runtime": "^7.0.0", "@babel/preset-env": "^7.0.0", "@babel/runtime": "^7.0.0", + "@rollup/plugin-json": "^4.0.0", "@rollup/plugin-replace": "^2.2.0", "npm-run-all": "^4.1.5", "rollup": "^1.12.0", diff --git a/example/rollup.config.js b/example/rollup.config.js index 29cd491..b46dcee 100644 --- a/example/rollup.config.js +++ b/example/rollup.config.js @@ -3,7 +3,7 @@ import replace from '@rollup/plugin-replace' import commonjs from 'rollup-plugin-commonjs' import svelte from 'rollup-plugin-svelte' import babel from 'rollup-plugin-babel' -import json from 'rollup-plugin-json' +import json from '@rollup/plugin-json' import { terser } from 'rollup-plugin-terser' import config from 'sapper/config/rollup.js' diff --git a/example/yarn.lock b/example/yarn.lock index 32f0a46..7a9b712 100644 --- a/example/yarn.lock +++ b/example/yarn.lock @@ -677,6 +677,13 @@ resolved "https://registry.yarnpkg.com/@polka/url/-/url-1.0.0-next.7.tgz#e0f307ab768b799aa8668343ce0df6601f29b9b1" integrity sha512-DOQhemlNfLQ7FZ6gdThARbeIjfhdM5fIqoPtgOJkO27r8A4njwiQSqx+qbReuIHEtx3fJyjSn2spMnsAHc0rFQ== +"@rollup/plugin-json@^4.0.0": + version "4.0.0" + resolved "https://registry.yarnpkg.com/@rollup/plugin-json/-/plugin-json-4.0.0.tgz#4462e83c7ad5544bef4a601a6e8450daedc4b69b" + integrity sha512-Z65CtEVWv40+ri4CvmswyhtuUtki9yP5p0UJN/GyCKKyU4jRuDS9CG0ZuV7/XuS7zGkoajyE7E4XBEaC4GW62A== + dependencies: + rollup-pluginutils "^2.5.0" + "@rollup/plugin-replace@^2.2.0": version "2.2.1" resolved "https://registry.yarnpkg.com/@rollup/plugin-replace/-/plugin-replace-2.2.1.tgz#94af20cb3d70cccdcec991d1f97dd373936ec544" @@ -1447,13 +1454,6 @@ rollup-plugin-commonjs@^10.0.0: resolve "^1.11.0" rollup-pluginutils "^2.8.1" -rollup-plugin-json@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/rollup-plugin-json/-/rollup-plugin-json-4.0.0.tgz#a18da0a4b30bf5ca1ee76ddb1422afbb84ae2b9e" - integrity sha512-hgb8N7Cgfw5SZAkb3jf0QXii6QX/FOkiIq2M7BAQIEydjHvTyxXHQiIzZaTFgx1GK0cRCHOCBHIyEkkLdWKxow== - dependencies: - rollup-pluginutils "^2.5.0" - rollup-plugin-node-resolve@^5.2.0: version "5.2.0" resolved "https://registry.yarnpkg.com/rollup-plugin-node-resolve/-/rollup-plugin-node-resolve-5.2.0.tgz#730f93d10ed202473b1fb54a5997a7db8c6d8523"