とりあえずアプリを英語対応→欧米OK…は甘かった

「とりあえずアプリを英語対応→欧米OK…は甘かった」への5件のフィードバック

  1. 業務の合間にプログラムを書いている、素人です。
    5年ほど前に、英語版のプログラムを公開していたら、ドイツ人の方からメールがあり、何を言われているのかわからなかったのですが、2、3回やり取りしているうちに、小数点記号としてドイツではカンマ(,)を使っていることが分かりました。そこで、英語版のプログラムで小数点記号がカンマでもOKのバージョンを作り、それを利用してもらっていました。ところが、英語版で2つのバージョンが必要になりますし、最近ポルトガル語系の人も利用するようになったので、1つのバージョンで対応できないかと考え、次のようなことをしました。これで、日本語版のWindowsでロケールをポルトガル語にしても、日本語にしても同じ処理をしてくれるようになりました。
    プロの方から見て、いかがでしょうか。
    プログラム言語は、素人なので、ExcelのVBAです。
    入力データから数値を取り出すために、数値から構成される文字列sujiを定義しました。
    VBAのVal関数は、カンマを数値の一部と解釈しません。

       If ("_" & Val("2.3") = "_2.3") Then 'in case of decimal marker is "."
          suji = "0123456789./"
       Else                                ' in case of decimal marker is ","
          suji = "0123456789,/"
       End If
    

    (VBAのヘルプより) Val 関数は、ピリオド (.) だけを有効な小数点の記号として認識します。
    文字列中に数字以外の文字が見つかると、Val 関数は読み込みを中止します。円記号 (\) やカンマ (,) など、通常は数値の一部とみなされる記号や文字も、Val 関数は数値として解釈しません。ただし、Val 関数は基数を示すプリフィックス &O (8 進数) や &H (16 進数) は認識します。

    以上です。
    失礼します。

  2. OISHIさん

    こんばんは。

    コード中の”2.3″は、実際にはユーザが入力した文字列になる…という理解で良いでしょうか?その前提でコメントさせていただきますね。

    考え方的には、ユーザ環境のロケールを見て判断するのではなくユーザ入力値を見て判断している点に少し懸念を感じました。具体例を挙げますと、ドイツ語圏では小数点区切り記号がカンマであると同時に桁区切り記号がピリオドになりますので、ドイツ語圏のユーザが「1.000」(10^3)などと書いた場合、「1」と解釈してしまう恐れがあるのでは、と思いました。入力データが1000を超えることは無い、あるいは桁区切り記号の入力は禁止されている、という話であれば何も問題は無いのですが、そうでなければ対策した方が良いかもしれません。

    対策としては、Val関数の代わりにCDbl関数やCInt関数などを使えるようであれば、それが一番早いかと思います。これらの関数はVal関数と異なり、ユーザのロケールに応じて小数点記号などを切り替えてくれる(らしい)ので。もしCDblやCIntで代替不可であれば、話がややこしくなります。というのも、ある数値を表した文字列があったとき、それだけを見て小数点区切り記号と桁区切り記号をプログラム的に判別することは不可能だからです。ユーザのロケールを知らなくては判別できませんから、面倒(らしい)な手順でロケール情報を取得して、現在のユーザ向けの適切な小数点区切り記号を得て使うことになります。ただ、正直なところ「そこまでやるか」感があります。

    個人的には、CDblやCIntで代替できるならそれで対策するのが良いと思います。代替不可であれば、実装は現在のままにして「桁区切り記号は禁止」の制限事項を付ける、あたりが良い落としどころかなと思います。

    一意見ですが、ご参考になれば幸いです。

  3. 丁寧なコメント、ありがとうございました。
    私の書き方がまずかったために、たいへん余計な手間をお掛けしてしまいました。
    実は、”2.3″は私が書いたコードの一部です。Yamamotoさんにコメントの前提を誤解させてしまいました。
    示したコードの1行目のif文は、利用しているOSのロケールが「小数点記号がピリオドであるロケール」か、「小数点記号がカンマであるロケール」かを判定する文です。ピリオドであれば、Trueになります。Val関数は、ロケールが何であれ、同じ振る舞いをして、たとえば英語でも独語でも”2.3″なら2.3を返し、”2,3″なら2を返します。投稿で引用したVBAのヘルプにそう書いてあり、テストしてもそうでした。WindowsAPIを利用すればロケールは分かるだろうけど、ロケール情報だけでは、そのロケールの小数点記号が何であるかは分かりませんし、またAPIの利用は面倒ですので、利用しませんでした。
    suji=”0123456789./” や suji=”0123456789./” の部分を
    Locale_eng=True や Locale_eng=False にして投稿すれば誤解を招かなかったかもしれないと反省しています。
    そして、次のようなコードをお示しすれば、良かったと思います

    If Locale_eng Then
       suji="0123456789./"
       Formula="#,###.0" '表示に使用する形式
       etc.
    Else
       suji="0123456789,/"
       Formula="#.###,0"
       etc.
    End If
    

    (VBAはVisualBasic6相当の古い言語のせいか) Valのような振る舞いをする関数があり、それを利用してロケールの分類ができました、という報告をして、それで良いのかをプロの方に診てもらおうと思い、投稿させてもらった次第です。
    お騒がせしました。

  4. OISHIさん、

    山本です。返信が遅くなってしまい申し訳ありません。

    すみません、一行目のコードの意味を読み違えていました…。

    1. 文字列と実数を対象にした & 演算子は、その実数を実行環境ロケールの書式で文字列化した後で結合する(ロケール依存処理)
    2. Val関数は、実行環境ロケールに存らず常にピリオドを少数点区切りに用いて実数を文字列化する(ロケール非依存処理)

    したがってピリオド区切りで記載した実数の文字列(たとえば”2.3″)をVal関数で実数に変換し、& 演算子で文字列に戻した場合、もし実行環境ロケールの小数点区切りがピリオドであれば「元通りになる」…この原理で小数点区切り記号を判定しているのですね。なるほど、原理的にも確実な動作が期待されますし、何も問題は無いと思います。

    なお、Val("2.3") とする代わりに 2.3 と実数リテラルを書いても良いかもしれません。というのも、Val関数に固定の文字列値を指定した結果は環境に依らず一定…つまり事実上「定数」であるからです。自分の環境(Office 365のMac版Excel)で次のようなIf文を書いてみたところ:

    If ("_" & 2.3 = "_2.3") Then
    ...
    

    実行環境ロケールにおける小数点区切りがピリオドであるかどうかを正しく判定できました。ご参考になれば幸いです。

  5. Yamamotoさま
    再度のコメントをありがとうございます。
    自分の文章が理解してもらえ、ホッとしました。
    その上、&演算子の仕様と、なお書きのコード例まで教えてくださり、ありがとうございます。
    試しに、WindowsのLocaleを日本語とポルトガル語にして、次のコードをVBAで実行させました。
    —-
    MsgBox (“” & 2.3)
    —-
    見事に、日本語 2.3 、ポルトガル語 2,3 と表示されました。
    これを使えば小数点記号の判別がより簡潔にできます。
    ありがとうございました。

コメントを残す

メールアドレスが公開されることはありません。

このサイトはスパムを低減するために Akismet を使っています。コメントデータの処理方法の詳細はこちらをご覧ください