サンプルの粒度が分からない
概要
簡単に触ったけど、たぶん案件そのものが流れるからもったいなくて残したかっただけのもの
要件
- アクセス時は日本語表示
- 英語/簡体語 のボタンを押下すると、押下したボタンに応じて言語が変更される
- 日本語 のボタンを押下すると現在のぺージにリダイレクト
奇妙に思われるかもしれないね
scaffold
vite のグローバルインストール
$ sudo npm install -g vite
vite でプロジェクト作成。今回はバニラ(Vanilla)でプレーン js
$ npm create vite
必要なパッケージのインストール。
jquery, bootstrap のバージョンは adminlte 3.1 のサンプルで使用されているバージョンに揃えたもの
$ npm install i18next i18next-http-backend jquery-i18next admin-lte@~3.1 jquery@~3.7 bootstrap@~4.6 // package.json "devDependencies": { "vite": "^5.4.10" }, "dependencies": { "admin-lte": "~3.1", "bootstrap": "~4.6", "i18next": "^23.16.6", "i18next-http-backend": "^2.6.2", "jquery": "~3.7", "jquery-i18next": "^1.2.1" }
開発時は基本的に vite のローカル web サーバを立てて行う。
ホットリロードなしで開発はちょっとね
$ npm run dev // ビルド: 初期設定なら dist ディレクトリ配下に出力される $ npm run build
ソース
いろいろファイル追加した後のディレクトリ構成
$ tree . . ├── dist ├── index.html ├── js │ ├── app.js │ ├── core_i18n.js │ └── index.js ├── locales │ ├── en │ │ └── index.json │ └── zh-CN │ └── index.json ├── node_modules ├── package-lock.json └── package.json
index.html の要旨
<div class="btn-group btn-group-toggle" data-toggle="buttons"> <label class="btn btn-secondary active"> <input type="radio" name="lang" autocomplete="off" value="jp" checked>日本語 </label> <label class="btn btn-secondary"> <input type="radio" name="lang" autocomplete="off" value="en">English </label> <label class="btn btn-secondary"> <input type="radio" name="lang" autocomplete="off" value="zh-CN">簡体語 </label> </div> <div class="for_translating"> <span data-i18n="text">日本語</span> </div> <script src="./js/app.js" type="module"></script> <script src="./js/index.js" type="module"></script>
app.js: 全ページで読み込むのを意図したもの。
import jQuery from "jquery"; window.$ = window.jQuery = jQuery; import "bootstrap"; import "admin-lte"; import "admin-lte/dist/css/adminlte.min.css";
index.js: index.html 用の画面個別 js。
想定では画面で名前空間を割るつもりだったので、名前空間と同義に扱うつもりだったけどなんだかんだあってやめた。
core_i18n からインポートした i18n() をコールすると翻訳が行われる。
import i18n from "./core_i18n.js"; i18n("jp", "index");
core_i18n.js: i18next の初期化処理等を行うコア部分
import i18next from "i18next"; import HttpApi from "i18next-http-backend"; import jqueryI18next from "jquery-i18next"; const defaultLang = "jp"; const i18n = (lang, name) => { i18next.use(HttpApi).init( { debug: true, lng: lang, fallbackLng: defaultLang, load: "currentOnly", backend: { loadPath: `../locales/{{ lng }}/${name}.json`, }, }, (err, t) => { console.log(err); jqueryI18next.init(i18next, $, { useOptionsAttr: true, }); document.getElementsByName("lang").forEach((radio) => { let value = radio.value; if (value == "jp") { // 日本語なら現在のパスにリダイレクト radio.onchange = () => { location.href = location.pathname; }; } else { // 指定された言語で翻訳 radio.onchange = () => { i18next.changeLanguage(value).then((t) => { $(".for_translating").localize(); }); }; } }); } ); }; export default i18n;
技術詳細
i18next の初期化オプション
- debug: コンソールにログ吐くかどうか
- lng: 選択した言語
- fallbackLng: 選択した言語に関する情報がないとかでエラーが起きた場合のフォールバック先言語
- load: 分かりにくい名前。lng に設定した言語コードの辞書探索ロジックを切り替えるパラメータで、currentOnly なら指定した言語だけを探す
- lng: "en-US" の場合、デフォルト(all)なら en-US, en, dev を探したりする
- backend: プラグインオプションの 1 つ。今回の場合は backend に i18next-http-backend を設定しています
- loadPath: 辞書のパス。i18next のパラメータを変数に指定できるみたいで {{ }} を用いればいいようです
言語を動的に切り替える
i18next.changeLanguage() をコールします。
当該関数は Promise を返却するので .then() でコールバックを記述できます。
今回の実装の場合、ボタンを押下した際に当該関数をコールして対応した辞書を読み込み、コールバックで翻訳してます。