0
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

CDN版Vue3でお手軽多言語対応

Last updated at Posted at 2023-11-07

はじめに

CDNで単一ファイルコンポーネントを作成する方法はこちらで紹介しました。
これに追加で、CDN版i18nを用いて多言語対応する方法をご紹介します。

結論

index.html
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    
    <title>TITLE</title>
    
    <script src="https://unpkg.com/vue@3/dist/vue.global.js"></script>
    <script src="https://unpkg.com/vue-i18n@9"></script>
    <script src="https://cdn.jsdelivr.net/npm/vue3-sfc-loader/dist/vue3-sfc-loader.js"></script>
    
    </script>
</head>
<body>
    <div id="app"></div>

    <script>
+       //i18n初期設定
+       const i18n = VueI18n.createI18n({
+            legacy: false,
+            locale: navigator.language,
+            fallbackLocale: "en",
+        });

        //vue3-sfc-loader初期設定
        const options = {
            moduleCache: {
                vue: Vue
            },

            //read subdirectory vue component file.
            async getFile(url) {
                
                const res = await fetch(url);
                if ( !res.ok )
                throw Object.assign(new Error(res.statusText + ' ' + url), { res });
                return {
                getContentData: asBinary => asBinary ? res.arrayBuffer() : res.text(),
                }
            },
            
            addStyle(textContent) {
        
                const style = Object.assign(document.createElement('style'), { textContent });
                const ref = document.head.getElementsByTagName('style')[0] || null;
                document.head.insertBefore(style, ref);
            },

+            //<i18n>タグの読み込み
+            customBlockHandler(block, filename, options) {
+
+                if ( block.type !== 'i18n' )
+                  return
+        
+                const messages = JSON.parse(block.content);
+                for ( let locale in messages )
+                  i18n.global.mergeLocaleMessage(locale, messages[locale]);
+            }
        }
        const { loadModule } = window["vue3-sfc-loader"];
        
        //Appコンポーネントをマウント
        const app = Vue.createApp(
            Vue.defineAsyncComponent(
                () => loadModule("./src/components/App.vue", options)
            ),
        )
        app.use(i18n);
        app.mount('#app');
    </script>
</body>
</html>
App.vue
<template>
+    {{ t("example.explain") }}
</template>

<script>
    export default Vue.defineComponent({
        name: 'App',
        components: {
        },
+        setup() {
+            //set up i18n
+            const { t } = VueI18n.useI18n()
+            return { t }
+        },
    })
</script>
+<i18n>
+    {
+        "en": {
+            "example": {
+                "explain": "This is how you use i18n"
+            }
+        }
+        "ja": {
+            "example": {
+                "explain": "こうやってi18nを使います"
+            }
+        }
+    }
+</i18n>

言語選択コンポーネントが欲しいならこちらをお使いください。

LanguageSelection.vue
<template>
    <select v-model="$i18n.locale">
        <option value="en">English</option>
        <option value="ja">日本語</option>
    </select>
</template>

<script>
    export default {
        name: 'LanguageSelection'
    }
</script>

解説

  • i18nのCDN版を用いています。

  • index.htmlの処理はメンドウなのでテンプレートと理解して大丈夫だと思います。

  • .vueファイルに、<i18n>タグとして、json形式で翻訳情報を書き込みます。
    HTML上に表示するには、{{t("PATH")}}のように書き込みます。

  • i18nの言語設定の変数はi18n.global.locale.valueにあります。(i18nindex.htmlで定義したグローバル変数)もし、テキスト以外に言語設定にレスポンスしたい場合は、computedにこの変数を組み込めば対応できます。

0
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?