1 |
|
2 |
|
3 |
|
4 |
|
5 |
|
6 |
|
7 |
|
8 |
|
9 | import {Locale, Locales} from 'locale';
|
10 | import fs from 'fs';
|
11 | import path from 'path';
|
12 |
|
13 | import {memoize} from 'fusion-core';
|
14 | import type {Context} from 'fusion-core';
|
15 |
|
16 | import type {TranslationsObjectType} from './types.js';
|
17 |
|
18 | export type I18nLoaderType = {
|
19 | from: (
|
20 | ctx: Context
|
21 | ) => {locale: string | Locale, translations: TranslationsObjectType},
|
22 | };
|
23 | export type LocaleResolverType = (ctx: Context) => string;
|
24 | export type LoaderFactoryType = (
|
25 | resolveLocales?: LocaleResolverType
|
26 | ) => I18nLoaderType;
|
27 |
|
28 | const defaultResolveLocales: LocaleResolverType = ctx =>
|
29 | ctx.headers['accept-language'];
|
30 |
|
31 | const loader: LoaderFactoryType = (resolveLocales = defaultResolveLocales) => {
|
32 | const readDir = root => {
|
33 | try {
|
34 | return fs.readdirSync(root);
|
35 | } catch (e) {
|
36 | return [];
|
37 | }
|
38 | };
|
39 | const root = './translations';
|
40 | const locales = readDir(root)
|
41 | .filter(p => p.match(/json$/))
|
42 | .map(p => p.replace(/\.json$/, ''));
|
43 | const data = locales.reduce((memo, locale) => {
|
44 | const parsedLocale = new Locale(locale);
|
45 | memo[parsedLocale.normalized] = JSON.parse(
|
46 | fs.readFileSync(path.join(root, locale + '.json'), 'utf8')
|
47 | );
|
48 | return memo;
|
49 | }, {});
|
50 | const supportedLocales = new Locales(locales);
|
51 |
|
52 | return {
|
53 | from: memoize(ctx => {
|
54 | const expectedLocales = new Locales(resolveLocales(ctx));
|
55 | const locale = expectedLocales.best(supportedLocales);
|
56 | const translations: TranslationsObjectType = data[locale.normalized];
|
57 | return {translations, locale};
|
58 | }),
|
59 | };
|
60 | };
|
61 |
|
62 | export default (((__NODE__ ? loader : null): any): typeof loader);
|