2017年4月
« 3月    
 12
3456789
10111213141516
17181920212223
24252627282930

カテゴリー

最近のコメント

<!–:ja–>JSONによるJavaScriptの国際化(文字列切り替え)<!–:–><!–:en–>JavaScript Internationalization with JSON<!–:–>

以前、JavaScript国際化プログラミング で、jQueryを使った、Javaプロパティファイルによる国際化(文字列切り替え)、および他の国際化ライブラリ(Glob(jquery-global)など)について書きましたが、今回は、jQueryを使わず、Pure Java JSONによる文字列切り替えについて書こうと思います。

オリジナルコンテンツは、ソフトウェア国際化ツールWorld Wide Navi付属の、国際化プログラミングの章になりますので、そちらも参照してください。

1.リソースファイルの作成

JSファイル内の埋めこみ文字列をJSONファイルに外部化します。

sample_1.js

var msg1 = "msg1:";
->var msg1 = wwnRs.sample1_1(*1);
function msgA() {
 alert(msg1 "Hello, this is a sample1 text.");
 ->alert(msg1 wwnRs.sample1_2(*1));
}

../wwnaviRs/wwnaviBundle.json

{
"sample1_1" : "msg1:",(*2)
"sample1_2" : "Hello, this is a sample1 text."(*2)
}

*1) wwn.sample1_1 = JSON変数.JSONキー
*2) “sample1_1″ : “msg1″ = “JSONキー” : “JSON値”
最後の”,”は削除する必要があります。削除しない場合、IEは正しくJSONを解析できません。

2.JSONのロード処理を他のJSファイルに作成

文字列をJSONに外部化した後、それらをユーザーロケール(ブラウザの言語設定)に適した形で、上記の変数にロードする処理を書く必要があります。 処理は、はじめに呼ばれる1つのJSファイル(この章では”wwnaviJs.json.js”と呼びます)にまとめて、HTMLヘッダーで読み込むことがのぞましいです。

HTMLヘッダー

<head>
...
<script src="wwnaviRs/wwnaviJs.json.js"
 type="text/javascript">
</script>
<script src="sample_1.js" type="text/javascript">
</script>
...

wwnaviJs.json.js (初期化コード)

// 通常のAjax HTTPリクエスト関数
function wwnaviHttpRequest(){
 if(window.ActiveXObject){
 try{
 return new ActiveXObject(
 "Msxml2.XMLHTTP");
 }catch(e){
 try {
 return new ActiveXObject(
 "Microsoft.XMLHTTP");
 }catch(e2){
 return null;
 }
 }
 }else if(window.XMLHttpRequest){
 return new XMLHttpRequest();
 }else{
 return null;
 }
}

// 「同期」処理でのAjaxによるファイル読み込み関数
// 通常のAjax通信は「非同期」ですが、
// それではファイル読み込みが完了するまで待機できないので、
// 「同期」方法を採用しています。
function wwnaviLoadJs(url){
 htoj = wwnaviHttpRequest();
 htoj.open("GET", url, false);
 htoj.send(null);
 return htoj.responseText;
}

// JSON変数(「wwnRs」は、sample_1.jsと同じである必要あり)
// の初期化
var wwnRs = eval("({"_rslang":""})");

// HTTPサーバーアクセスを通じてユーザーロケールを
// 取得するためのコールバック関数 (JSONP)
// (最後の行参照)
function wwnParseLang(json) {

  // 言語と国コード(例:en-us)を取得するための
 // HTTPヘッダー
 var l = ""; if(json["Accept-Language"]
 != undefined)
 l = json["Accept-Language"];
 if(l.indexOf(",") >=0) l = l.substring(0,
 l.indexOf(","));

 // マスターのJSONリソース(ロケールなしのもの)を、
 // JSON変数へ読み込む (同期Ajax).
 wwnRs = eval("("
 wwnaviLoadJs("wwnaviRs/wwnaviBundle.json") ")");
 wwnRs._rslang="default"; 

 try {
 // ユーザーロケール(変数"l")のJSONリソースを、
 // JSON変数に読み込む (同期Ajax).
 wwnRs = eval("("
 wwnaviLoadJs("wwnaviRs/" l
  "/wwnaviBundle.json") ")");
 wwnRs._rslang=l; 
 // 使用されたリソースのロケールコードを設定
 }catch(e){
 // エラー(ユーザーロケールのリソースが見つからない)
 // 場合、マスターを使用
 }

 wwnRs._ulang=l; 
 // 検出したユーザーロケールを設定

}

// ユーザーロケールを取得するために、
// jQuery browser languageライブラリ(*)の
// JSONP APIを使用していますが、
// 他のものを使うことも可能です。
document.write(
"<script
src="http://ajaxhttpheaders2.appspot.com/
?callback=wwnParseLang"
type="text/javascript"></script>"
);

*)jQuery browser languageライブラリについては、
GitHubを参照してください。

3.JSONファイルの配置

マスターJSONファイル(ステップ1の”wwnaviRs/wwnaviBundle.json“)と翻訳(ローカライズ)されたファイルを、上記の初期化コードに従い、ロケールのディレクトリに配置します。

ローカライズされたリソース =
 wwnaviRs(リソースパス)/ユーザーロケール/
   wwnaviBundle(リソース名).json

ローカライズされたリソースを追加するだけで、JavaAScriptメッセージをユーザーの言語設定に基づいて切り替えられます。

../wwnaviRs/wwnaviBundle.json ... 英語 (デフォルト)
../wwnaviRs/ja/wwnaviBundle.json ... 日本語
../wwnaviRs/ko/wwnaviBundle.json ... 韓国語

これらの処理は、World Wide Navi内のJavaScriptの文字列外部化のサンプルで確認できます。



&amp;amp;lt;!–:ja–&amp;amp;gt;JavaScript 国際化プログラミング&amp;amp;lt;!–:–&amp;amp;gt;&amp;amp;lt;!–:en–&amp;amp;gt;JavaScript Internationalization Programming&amp;amp;lt;!–:–&amp;amp;gt;

JavaScriptはブラウザによって実行されるクライアント向けスクリプト言語ですが、その国際化の標準的な仕様はありません。
ここでは、一般的なポイント、および主要なライブラリを使った国際化について説明します。

※jQueyを使わないJSONを使った国際化については、こちらを参照してください。

ロケール、書式、タイムゾーン

JavaScriptの一般的なプログラミングでの国際化のポイントを以下に挙げます。
.NET AjaxライブラリやjQuery、その他固有のライブラリの情報については各情報リソースを参照ください。

  1. ユーザーロケール(言語と地域)の判定
    ユーザーの使用する言語や住んでいる地域によって、書式やメッセージを切り替えたい場合、そのユーザーのロケール(言語と地域の情報)を取得する必要があります。
    JavaやPHPといった通常のプログラミング言語には、これらの情報を取得する関数がありますが、JavaScriptにはこれらと等価のものはありません。
    一般的なJavaScriptのプログラミングでは、ユーザーの使用するブラウザの言語情報から言語を取得します。
    例えば、ユーザーの使っているFirefoxが日本版か英語版かということです。
    この情報は、殆どのブラウザにおいて、設定画面で変えられる言語設定の情報ではないことに注意が必要です。
    以下は、ブラウザの言語情報から言語コードを切り出す簡単なコードです。

    function wwnaviGetLang(){
    return (navigator.userLanguage||navigator.browserLanguage||navigator.language).substr(0,2);
    }

    このコードは、日本語版ブラウザを使っているユーザーの言語は日本語ということを意味します。
    OSの言語設定や、サーバーにアクセスする時のHTTPリクエストに入れられる言語情報などは、反映されないことに注意が必要です。

    地域については、上記のコードの2文字目以降にセットされている場合もありますが、保障はありません。
    なお、後述のUTCとの時差によって代表的なものを取得することはできますが、これも正確な判定ではありません。

    *ブラウザの言語設定を反映させたい場合には、jQuery-Browser-Languageという、リモートホストにアクセスし、HTTPリクエストの言語を抽出する(ブラウザの言語設定を認識する)jQueryライブラリがあります。

  2. 以下はそのライブラリを使ったサンプルコードです。

    $.browserLanguage(function( language , acceptHeader ){
    var l = acceptHeader; l = l.substring(0,2);
    alert(l); // これはHTTPリクエストヘッダーを解析し、
    // “en”, “ja”…といったブラウザ言語設定と同じ値を返します。
    });

  3. 日付、通貨などの書式
    JavaやPHPといった主要なプログラミング言語には、ロケールに沿った書式変換をする関数、クラスがありますが、JavaScriptにはそういった関数はありません。
    もし、ユーザーの言語情報などによって書式を切り替えたい場合は、そういった処理を作りこむ必要があります。
    これらを全言語分作成するのは大変ですが、.NET AjaxやjQueryなどのライブラリにはそういった汎用ライブラリが用意されています。

    (※jQueryには、日付、通貨などの多言語用ライブラリとしてGlobがあります。)

    例えば、日付や通貨を書式変換して表示している個所は、固定の書式が使われていないか確認し、切り替えの必要がある場合は、上記のようなライブラリを使うことをお勧めします。

    書式については、文字列の書式文化固有の表現も参照してください。

  4. ユーザーのタイムゾーンを取得する
    JavaScriptには、タイムゾーンを取得する関数はありませんが、UTC(世界標準時間)とクライアントPCの時計の時差を求める関数があります。
    これにより、サーバーの共通時間を各クライアントPCの時間に変換するといった処理ができます。

    また、UTCとの時差から、代表的なユーザーの地域を特定することができます。
    以下は、UTC(世界標準時間)とクライアントPCの時計の時差を時間単位で求めるコードです。

    function getTzOff() {
    var date = new Date();
    return tzoff = ( date.getHours() – date.getUTCHours() 24 ) % 24;
    }

    この情報に、下記のような時差と地域の対応表を合わせることで、javaScriptからユーザーの代表的な地域を予想することができます。

    0=GB
    1=IT
    2=FI
    3=RU
    4=AE
    5=PK
    6=BD
    7=ID
    8=PH
    9=JP
    10=AU
    11=NC
    12=NZ
    13=TO
    14=TO
    15=US
    16=US
    17=US
    18=US
    19=US
    20=CL
    21=BR
    22=BR
    23=GL

    (上記の国コードをタイムゾーンのIDに変えれば、
    サーバー側でユーザーの代表的なタイムゾーンも予測できます)
    *同じ時差に対応する地域がいくつもあることに注意が必要です。
    実際には、ユーザーが自分の地域を後で設定できるようにする必要があります。

jQueryを使った国際化

jQieuryのライブラリjquery.i18n.propertiesを使った、Javaプロパティファイル形式でのリソース管理について記述します。

  1. リソースファイル(プロパティファイル)の作成
    JSファイルに埋めこまれている文字列をプロパティファイル(.properties)に記述(外部化)します。プロパティファイルの作成については、Java国際化プログラミング – メッセージをご参照ください。
  2. jQueryライブラリを読み込む
    必要なJSファイル(jquery.min.js、jquery.i18n.properties.js)を読み込みます。
    以下の二つの方法があります。

    A. 元のHTMLのスクリプトタグに埋めこむ (通常の方法)

    <head>

    <script src=”js/jquery.min.js” type=”text/javascript”></script>
    <script src=”js/jquery.i18n.properties.js” type=”text/javascript”></script>

    * 呼出し元のHTML全てに埋めこむ必要あり。

    B. 各JSから動的に読み込む。

    function wwnaviHttpRequest(){
    if(window.ActiveXObject){
    try{
    return new ActiveXObject(“Msxml2.XMLHTTP”);
    }catch(e){
    try {
    return new ActiveXObject(“Microsoft.XMLHTTP”);
    }catch(e2){
    return null;
    }
    }
    }else if(window.XMLHttpRequest){
    return new XMLHttpRequest();
    }else{
    return null;
    }
    }
    function wwnaviLoadJs(url){
    htoj = wwnaviHttpRequest();
    htoj.open(“GET”, url, false);
    htoj.send(null);
    return htoj.responseText;
    }

    eval(wwnaviLoadJs(“wwnaviRs/jquery.min.js”));
    eval(wwnaviLoadJs(“wwnaviRs/jquery.i18n.properties.js”));
    * 必要なJSファイルを同期通信(*1)で読み込み、実行しています。

    … (JSのコード)

    (*1)非同期通信の場合、読み込みが完了する前にコードが実行されるのでうまく処理されません。

    * 各JSファイルのコード量が増えますが、呼出し元のHTMLを修正する必要がありません。wwnaviでは自動化を実現するため、デフォルトではこの方法をとっています。

  3. 初期化コードの記述
    上記の読み込みの直後に、プロパティファイルの場所や名前、対象言語などを設定する処理を記述します。

    jQuery.i18n.properties({name:”wwnaviBundle(*1)”,path:”wwnaviRs(*2)/”,mode:”both”,
    language:wwnaviGetLang()(*3),callback:function(){}});

    (*1)プロパティファイルの名前(基底名)です。
    (*2)プロパティファイルのパスです。
    (*3)対象の言語コード(“en”や”ja”など)です。この場合、以下のようなブラウザの言語情報を取得する関数を作成して指定しています。

    function wwnaviGetLang(){
    return (navigator.userLanguage||navigator.browserLanguage||navigator.language).substr(0,2);
    }

    *ブラウザ設定の値を使いたい場合は、jQuery-Browser-Languageが使えます。
    これはリモートホストにアクセスすることで、HTTPリクエストヘッダーを読むことができます。

    以下はこのライブラリを使った初期化コード(ブラウザの設定を認識可)です。

    $.browserLanguage(function( language , acceptHeader ){
    var l = acceptHeader; l = l.substring(0,2);
    jQuery.i18n.properties({name:”wwnaviBundle”,path:”wwnaviRs/”,mode:”both”,language:l,callback:function(){}});
    });

    ※ブラウザの言語情報の取得については、ロケール、書式、タイムゾーンをご参照ください。

  4. メッセージ読み込み処理を記述する。
    メッセージ読み込みのコードを文字列の位置に埋めこみます。

    var msg1 = jQuery.i18n.prop(“sample1_1(*1)”);

    (*1)1.で作成したプロパティファイルの対応するキーです。

  5. .propertiesファイルを配置する。
    .propertiesファイルを初期化コードで指定したパスに配置します。
    ファイル名は以下の規則に従います。
    基底名(例:”wwnaviBundle”) “_” 言語名(例:”ja”)
    基底名だけのファイルはデフォルトのリソースとなり、対応する言語のものがある場合は、そちらが読み込まれます。
    以下のように言語分のリソースを追加するだけで、言語を切り替えができるようになります。

    ../wwnaviRs/wwnaviBundle.properties … English (default)
    ../wwnaviRs/wwnaviBundle_ja.properties … Japanese
    ../wwnaviRs/wwnaviBundle_ko.properties … Korean

上記はWorld Wide Navi付属のJavaScriptの文字列の外部化サンプルで確認できます。

gettextを使った国際化

JavaScriptのgettext、サンプルなどはこちらから入手できます。

C言語版gettextについてはgettext によるメッセージ処理をご参照ください。

.NET Ajaxライブラリを使った国際化

.NET Ajaxライブラリについてはをご参照ください。

※オリジナルソース:

ソフトウェア国際化ツール World Wide Navi JavaScript国際化プログラミング



&amp;amp;lt;!–:en–&amp;amp;gt;A little tips for Perl, PHP, JavaScript&amp;amp;lt;!–:–&amp;amp;gt;&amp;amp;lt;!–:ja–&amp;amp;gt;Perl, PHP, JavaScriptのちょっとしたTIPS&amp;amp;lt;!–:–&amp;amp;gt;

最近、久々にPerl、PHP、JavaScript、ちょっとだけはまったところのメモ。

意外と下記に言及されているサイトが少なかったんで。

Perl

文字列を区切り文字で分割して配列で受け取る場合について。

@data = split(/\t/ ,$line);

などは、空文字が途中にある場合、空文字以降捨てられてしまいます。

(無視されて切り詰められるのかと思いきや切捨てられるとは。)

最後の引数に-1をつければいいとサイトには書いてありますが、

@data = split(/\t/, $line, -1);

でもダメです。

@data = split(“\t”, $line, -1);

のように正規表現の所を文字列に変えると空文字も配列の1要素として格納されます。

TSVデータを外部から受け取って処理する場合など、配列の全要素の位置が固定のほうがいい場合は上記のコードがおすすめです。

PHP

クッキーの書き込みのタイミング。

setcookieでクッキーを書く場合、HTMLをoutputする前に書かないと書き込まれません。

(クッキーはヘッダー情報なので当然と言えば当然ですが。)

PHPと言うよりHTMLを直接書けるSCRIPT言語共通の仕様だと思います。

処理のあとに、一度にHTMLを吐きだすようなコードだとあまり関係ありませんが、

<%や<?phpなどでHTMLとロジックが混在していて、かつそれが他人のコードだったりすると、

「あれ?クッキー書かれてない。->ブラウザの問題?->セキュリティ設定?」などとあらぬ方向へ迷いこんでしまうこともあります。(ぼくみたいなおっちょこちょい君は特に)

JavaScript

画面表示時にウインドウを最大化する。

<script type=”text/javascript”>

<!–

window.resizeTo(screen.availWidth, screen.availHeight);

window.moveTo(0,0);

//–>

</script>

でウインドウを最大化(正確に言うと、スクリーンとほぼ同じサイズ)出来ますが、このままだとIEでは最大化されません。

IEにも対応させるには、

<script type=”text/javascript”>

<!–

window.moveTo(0,0);

window.resizeTo(screen.availWidth, screen.availHeight);

//–>

</script>

です。

ちなみに、moveToがなくてもダメ。理由は、IEの場合、resizeToが実行されるときに画面からはみ出るように大きくしてくれないから。つまり最初に中央に移動して、延ばせる領域を作ってから拡大するということです。