6
4

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

ブラウザにおける多言語対応

Last updated at Posted at 2022-12-21

この記事の読者

  • WebでPHPをあまり使ったことがない方
  • 多言語対応させたいけど、SQLなどは使いたくない方
  • この記事を楽しく読める人

きっかけ

自分の運営している団体でWebを多言語対応させよう思った時に、WordPressなどは使わず、一からWebを構築しているため、自ら多言語対応をする必要があった。

前提条件

  • 使えるのはHTML、CSS、JavaScriptの3つだけ。
  • 外部ライブラリを使うのは問題ない
  • 翻訳を担当するのは別の人

結論

JSONファイルを作成→配列から読み込み

追記(2022/12/24)

@think49 様より、コード改善のアドバイスをいただきました。
誠に感謝しかございません。
のちにその修正コードを追記させていただきます。

詳細

例として以下のHTMLファイルを用意。

index.html
<!DOCTYPE html>
<html>
    <head>
        <title>test<title>
    </head>
    <body>
        <h1 name="enterd"> 果物</p>
        <p name="enterd">りんご</p>
    </body>
</html>
data.json
[
    {
        "lang":"ja",
        "value":{
                "title":"果物",
                "text":"りんご"
            }
    },
    {
        "lang":"en",
        "value":{
                "title":"Fruits",
                "text":"Apple"
            }
    }
]
main.js
//初期値の設定
let langNum = 3;

//パラメータの取得
function getParam(name, url) {
    if (!url) url = window.location.href;
    name = name.replace(/[\[\]]/g, "\\$&");
    var regex = new RegExp("[?&]" + name + "(=([^&#]*)|&|#|$)"),
        results = regex.exec(url);
    if (!results) return null;
    if (!results[2]) return '';
    return decodeURIComponent(results[2].replace(/\+/g, " "));
};

//言語のパラメータがある場合は取得、ない場合はブラウザの言語を取得
if (getParam("lang") == null) {
    const browserLangugage = window.navigator.language;
    setLanguage(browserLangugage);
    console.log("No language")
} else {
    setLanguage(getParam("lang"));
    console.log("Para")
}

//JSONから言語の取得をするための変換
function setLanguage(lang) {
    if (lang == "ja") {
        langNum = 0;
        console.log(langNum);
    } else if (lang == "en") {
        langNum = 1;
        console.log(langNum);
    } else if (lang == "es") {
        langNum = 2;
        console.log(langNum);
    } else {
        langNum = 1;
        console.log(langNum);
    };
};

//JSONファイルから言語データを取得
fetch('./data.json')
    .then(function (response) {
        console.log(response);
        return response.json();
    })
    .then(function (data) {
        console.log(langNum);
        let valueArray = Object.values(data[langNum].value);
        console.log(valueArray);
        return valueArray;
    })
    .then(function (valuesOfInfo) {
        const length = valuesOfInfo.length;
        for (let i = 0; i < length; i++) {
            document.getElementsByName("enterd")[i].innerHTML = valuesOfInfo[i];
        }
    })

JSONファイルの中が配列なので、パラメータで指定されている言語と対応する番号(配列インデックス)に変換する必要がある。
たとえば、URLは表記は以下の通りになる。

https://example.com/?lang=ja

だが、JSONのファイルの中では一つ目の配列にデータが入っているので、パラメータがjaならlangNum変数に0を入れる、のように対応させている。

利点

  • 他の言語の追加が容易である
  • 編集が簡単

改善すべきポイント

  • JSONを配列に変換しているので、一つでも忘れたら修正作業が大変

筆者の戯言

結局、Webページの多言語対応ってどのようにやるのが正解なんですかね?

修正1 (2022/12/24)

@think49 の修正版コードを追記します。
詳しくは、コメント欄を参照いただけると幸いです。
再度、 @think49 様に感謝申し上げます。

sample.html
<!DOCTYPE html>
<html lang="ja">

<head>
	<meta charset="utf-8">
	<title>sample</title>
</head>

<body>
	<template id="sample">
		<h1>${title}</h1>
		<p>${text}</p>
	</template>
	<script>
		'use strict';
		function replaceTextNode (entries, ...contextNodeList) {
			for (let contextNode of contextNodeList) {
				const xpathResult = document.evaluate('descendant::text()', contextNode, null, XPathResult.ORDERED_NODE_SNAPSHOT_TYPE, null);
				let i = xpathResult.snapshotLength;

				while (i--) {
					const textNode = xpathResult.snapshotItem(i);
					for (let [key, value] of entries){
						textNode.data = textNode.data.replace(new RegExp('\\${' + key + '}', 'g'), value);
					}
				}
			}
		}

		fetch('lang.json')
		.then(response => response.json())
		.then(contentEntries => {
			const lang = new URLSearchParams(location.search).get('lang');
			const contents = contentEntries[lang];

			if (!contents) return;
			document.documentElement.lang = lang;

			const df = document.getElementById('sample').content.cloneNode(true);
			replaceTextNode(Object.entries(contents), ...df.childNodes);
			document.body.appendChild(df);
		});
	</script>

</body>

</html>
lang.json
{
  "ja":{
    "title": "果物",
    "text": "りんご"
  },
  "en":{
    "title": "Fruits",
    "text": "Apple"
  }
}
6
4
5

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
6
4

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?