Closed3
Remix-i18nextをVercelで使いたい
普通に使う
こちら を参考に普通に作るとVercelにデプロイしたときにpublic/locales/**
が読めなくて怒られる
remix-i18nextのサンプルから抜粋
import { RemixI18Next } from "remix-i18next";
import { FileSystemBackend } from "remix-i18next";
// You will need to provide a backend to load your translations, here we use the
// file system one and tell it where to find the translations.
let backend = new FileSystemBackend("./public/locales");
export let i18n = new RemixI18Next(backend, {
fallbackLng: "en", // here configure your default (fallback) language
supportedLanguages: ["es", "en"], // here configure your supported languages
});
カスタムバックエンドを使う
公式のREADMEの一番下に言語ファイルをCDNにおけるサービスを使えるよ、とあるので使ってみる
remix-i18nextのサンプルから抜粋
import type { Backend } from "remix-i18next/backend";
export class FetchBackend implements Backend {
private url: URL;
constructor(url: string) {
this.url = new URL(url);
}
async getTranslations(namespace: string, locale: string) {
let url = new URL(`${locale}/${namespace}.json`, this.url);
let response = await fetch(url.toString(), {
headers: { accept: "application/json" },
});
return response.json();
}
}
Locizeを使う
Locize
が公式でRemix-i18nextの対応方法を書いてくれてるのでやってみる
が、結局Locizeで言語ファイルを管理するだけでローカルにダウンロードして使おう!って感じなので根本解決にならない
LocizeのCDNから言語ファイルを持ってきたい
Locizeのサンプルリポジトリをみてみるとi18-next用のLocizeBackendが使えると思うけどDL数(CDNからの?)が増えると思うよ
と書いてあるのでとりあえず試してみる
TypeScriptで作ってるので諸々型を指定
import {Language, RemixI18Next} from "remix-i18next";
import i18nextOptions from "~/i18nextOptions";
import I18NextLocizeBackend from "i18next-locize-backend"
class LocizeBackend {
private locizeBackend: I18NextLocizeBackend;
constructor(options: { projectId: string, apiKey?: string, version?: string }) {
this.locizeBackend = new I18NextLocizeBackend(options);
}
async getTranslations(namespace: string, locale: string) {
return new Promise<Language>((resolve, reject) => {
this.locizeBackend.read(locale, namespace, (err, ret) => {
resolve(ret);
})
})
}
}
const backend = new LocizeBackend({projectId: "LOCIZE_PROJECT_ID});
// const backend = new FileSystemBackend("./public/locales");
export const i18n = new RemixI18Next(backend, {
fallbackLng: i18nextOptions.fallbackLng,
supportedLanguages: i18nextOptions.supportedLngs,
});
するとgetTranslations
が返すPromiseのリゾルバが型不一致のエラーを返す
this.locizeBackend.read
のcallbackが成功時に入れる値の型を見てみると
ret?: boolean | ResourceKey | null | undefined
こうなってる
ResourceKey
の定義を見ると
export type ResourceKey =
| string
| {
[key: string]: any;
};
で、帰ってきてほしいLanguage
の定義が
declare type Value = string | Language;
declare type Key = string;
export declare type Language = {
[key: Key]: Value;
};
こうなので、read
の結果がResourceKey
に特定できるまでチェックを入れまくる
async getTranslations(namespace: string, locale: string) {
return new Promise<Language>((resolve, reject) => {
this.locizeBackend.read(locale, namespace, (err, ret) => {
if (err) return reject(err);
if (!ret) return reject();
if (typeof ret === "boolean") return reject();
resolve(ret as Language);
})
})
}
最高に不格好&エラー時の挙動が全くわからんがとりあえずこれでRemix-i18nextを使ったRemixプロジェクトをVercel上でi18n対応できた
Remix or NextJSとLocizeのプロを探す旅
このスクラップは2022/04/02にクローズされました