設定
設定例
ライブラリを初期化する最小構成の設定例は次のようになります。 src/__layout.svelte
に次のように書いてください:
import { addMessages, init } from 'svelte-intl-precompile';
import en from '$locales/en';
import es from '$locales/es';
addMessages('en', en);
addMessages('es', es);
init({
initialLocale: 'en',
fallbackLocale: 'en'
});
これだけでも使いはじめることはできますが、もう少し深堀りしてみましょう。
ロケールの静的ロード
前記の例で見たように、ロケールを追加する最も簡単な方法は、それらを単にモジュールとしてインポートし、次の関数を使って登録することです: addMessages(langCode, translations)
.
import en from '$locales/en';
import es from '$locales/es';
addMessages('en', en);
addMessages('es', es);
翻訳をJSONファイルとして定義したにも関わらず、ここではそれらを JavaScript のモジュールとしてインポートしていることに注意してください: $locales
これは、ビルド時にコンパイラが翻訳をインライン関数を含むモジュールとしてコンパイルしているためです。
この方法では、もし一つの言語しか表示されない場合でも、すべての言語がロードされます。新しいプロジェクトを始めるときやごく少数の翻訳しか必要ない場合には大抵はこれで十分ですが、アプリケーションの規模が大きくなれば、必要に応じて翻訳を読み込むことを検討すべきでしょう。
ロケールの動的ロード
かなりの量の翻訳キーやたくさんのロケールがある場合、実際には表示しないすべての言語をあらゆるユーザにロードさせることは大変な無駄といえます。このライブラリでは register(langCode, callback)
関数を使ってユーザが選択した言語を動的にロードすることができ、 waitLocale(locale = defaultLocale)
関数でそれらのロケールがロードされるまで待つことができます。
すべてのロケールが動的にロードされるのであれば、デフォルトのロケールがロードされるまではレンダリングを待たせたいはずです。この関数を Svelte の load
関数の中で呼び出すことにより、まさにそれが実現できます。
import { init, register, waitLocale } from 'svelte-intl-precompile';
register('en', () => import('$locales/en'));
register('es', () => import('$locales/es'));
export async function load() {
init({ initialLocale: en });
await waitLocale(); // awaits the default locale, "en" in this case.
}
ロケールの動的ロード(ただし、今回は短く)
もし単にすべてのロケール(その言語に対しての翻訳を含むJSONファイルがあるすべてのロケール)を登録したいのであれば、便利な省略記法があります。 $locales
フォルダはさらに踏み込んだ機能を持つモジュールとなっていて、2つのユーリティティ関数を提供します: registerAll
と availableLocales
.
1つ目は、すべてのロケールに対して register(langCode, callback)
を呼び出すのと同様の働きをします。
2つ目は、利用可能な全てのロケールを含む配列(登録済みかどうかに関わらず)で、必要に応じて様々な目的に使うことができます。
import { init, waitLocale } from 'svelte-intl-precompile';
import { registerAll, availableLocales } from '$locales';
registerAll();
export async function load() {
init({ initialLocale: selectBestMatchingLocale(availableLocales) });
await waitLocale();
}
デフォルトロケールとフォールバックロケール
関数 init(libOptions)
の呼び出しにおける最も重要なオプションは initialLocale
と fallbackLocale
です。1つ目はアプリが最初に表示されるときに使うロケールを決定し、もう1つはそのとき選択されているロケールに欠けている翻訳があった場合に参照されます。
init({
initialLocale: 'es',
fallbackLocale: 'en'
});
最適なユーザ体験を実現する方法は、ログインユーザに対しては initialLocale
をユーザの言語設定に合わせたり、再訪問ユーザの場合であればクッキーから言語設定を読み出すようにしたり、またはSSRの時点でHTTPリクエスト中の Accept-Language
ヘッダを元に選択したりなど、様々な方法が考えられますが、最も単純明快な方法は、ユーティリティ関数を使ってブラウザやURLから検出することです。
最適なロケールを見つける
There are many valid strategies to select the best locale to pass to the init()
関数に渡すべき最適なロケールを選択する有効な方法は様々あります。このライブラリは特に一般的な方法を実装したヘルパー関数を提供しています。
getLocaleFromNavigator()
- ブラウザのロケール設定を取得します。結果的に、オペレーティングシステムのロケール設定を取得することになります。
getLocaleFromQueryString(key)
- URLのクエリ文字列のキーを指定して、ロケールを取得します。
例えば、/users?sort=name&dir=asc&lang=es
ならgetLocaleFromQueryString("lang")
を指定します。 getLocaleFromHash(key)
getLocaleFromQueryString
と同様のことを、URLハッシュフラグメントに対して行います。
例えば、/users#sort=name&dir=asc&lang=es
ならgetLocaleFromHash("lang")
を指定します。getLocaleFromPathname(regex)
- URLのパスからロケールを取得します。
例えば、myapp.com/en-US/users
なら、getLocaleFromPathname(/^/((es|en)(-\w\w)?)/)
とします。 getLocaleFromHostname(regex)
- ホスト名からロケールを取得します。
例えば、https://pt.myapp.com
ならgetLocaleFromHostname(/^((es|en)(-\w\w)?)\./)
とします。 getLocaleFromAcceptLanguageHeader(header, availableLocales?)
- Extracts the locale from the Accept-Language header based on a list of available locales. If availableLocales is omitted, returns the first language from the header.
E.g.getLocaleFromAcceptLanguageHeader('en-GB,en;q=0.9,es-ES;q=0.8,en-US;q=0.6', ['fr', 'es', 'de'])
for'es'
カスタム形式
このライブラリは、数値・日付・時間をフォーマットすることもできます。モダンブラウザや Node.js に既に存在する Intl API を活用することで、アプリを肥大化させることなく実現しています。
デフォルトでは以下のフォーマットが使えますが、必要に応じて追加することもできます。
{
number: {
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' }
}
}
もしカスタムのフォーマットを定義する必要があれば、 formats
オプションを使って初期化時にライブラリに渡せば、前述のデフォルトフォーマットにディープマージされます。フォーマットは、 Intl.DateTimeFormat
のオプションとして有効な値でなくてはなりません。詳細:
Intl.DateTimeFormat.
init({
fallbackLocale: 'en',
initialLocale: 'en',
formats: {
date: {
abbreviated: { weekday: 'long', month: 'short', day: 'numeric' }
},
time: {
'just-hour': { hour: 'numeric' }
}
}
});
For numbers specifically you can register your own formats like that or you can use Number Skeletons as a more flexible way of customizing every single aspect of how numbers are rendered. Check the crash course here