Actions

開発者エリア/言語ストリング

From Mahara Wiki

作成中です - mits (talk)

国際化 (i18n) およびローカライゼーション (l10n) の目的のため、Maharaでユーザに表示されるストリングすべてはコードに直接記述されるのではなく、「言語ストリング」に保存された上で get_string($identifier, $section) 関数により表示されます。この関数は外国語の言語パックがインストールされているか確認します。また、カスタム言語ファイルが存在するか確認して、存在する場合、そのストリングを使用します。そうでない場合、コア言語ファイルに戻ります。

PHPでのget_string()の使用方法

関数get_string()には以下のパラメータがあります:

  • identifier: 言語ストリング名です。セクション内ではユニークです。identifierはPHP配列キーとして受け入れられるべきです。慣習により言語ストリング名は英語コンテンツと同じものであり、すべてスペースなしの半角英字です。ストリングの正確な表現の代わりにストリングの目的をストリング名として使用できます。
  • section: 言語ストリングが存在するファイルです。これは技術的に任意です。無視された場合、多くの一般的なコアストリングを含むデフォルトの「mahara」セクションが割り当てられます。
    • 例:
      • 'admin': コアの「admin」セクション用です。
      • 'artefact.blog': 「blog」アーティファクトプラグイン用です。
      • 'theme.primaryschool': 「primaryschool」テーマ用です。
  • params: (任意) 言語ストリングには1つまたはそれ以上のsprintf()パラメータを含めます。言語ストリング内に存在する場合、get_string() がコールされて使用するストリングを配置するためにパラメータ値との合致が要求されます。パラメータは異なる語順の言語への翻訳時に役立ちます。

例:

$yesstr = get_string('yes');                     // lang/en.utf8/mahara.php
$clamstr = get_string('pathtoclam', 'admin');    // lang/en.utf8/admin.php
$blogstr = get_string('blog', 'artefact.blog');  // artefact/blog/lang/en.utf8/artefact.blog.php
$copyrightstr = get_string('feedrights','artefact.blog', $USER->displayname); // パラメータ付き言語ストリング

// 複数形ストリング。最初の変数は複数形アイテムの数です。get_stringは単一または複数のどちらを使うか決定するために変数を使用します (英語以外の言語では2つ以上の複数形が存在する場合があります)。
$updatefilesstr = get_string('updatednfiles', 'mahara', 5);

Dwooテンプレートからの言語ストリング使用方法

あなたは {} タグを使ってDwoテンプレート内部から言語ストリングにもアクセスできます:

{str tag='identifier' section='section' arg1='first param value' arg2='second param value'}

これを動作させるコードは次のとおりです: htdocs/lib/dwoo/mahara/plugins/function.str.php

JavaScriptからの言語ストリングの使用方法

プリフェッチ

あなたはJavaScriptでも言語ストリングを使用できます。最初にsmarty()関数に$pagestrings変数を渡して言語ストリングを読み込んでください ...

// Providing a $pagestrings variable to smarty()
$pagestrings = array(
     'admin' => array(
         'discardpageedits',
         'pathtoclam'
     ),
     'mahara' => array('yes')
);

... そして、次にJavaScriptのget_string()関数を使用して言語ストリングにアクセスできます。これは「section」セクションを除外する以外、PHPのget_string()に似ています (注意: これはあなたが2つの言語ストリングを同じIDで異なるセクションに含めないことを意味します)。また、「%s」タイプの置換パラメータのみ受け付けます。

<script type="text/javascript">
    alert(get_string('yes'));
    confirm(get_string('discardpageedits', 'first param value'));
</script>

特定のJavaScriptファイルがDwooに含まれる場合にJavaScriptのget_string()で多くのJavaScriptストリングを常に使用できるようハードコードされています。このリストに関して「htdocs/lib/web.php」の関数「jsstrings」をご覧ください。

AJAX経由で動的に取得する

Mahara 15.10現在、あなたはAjax経由で動的に言語ストリングも取得できます。get_string_ajax()関数を使用してください。事前に取得した言語ストリングとは異なり、動的に取得したストリングにはセクションパラメータおよび他のパラメータを含めます。この機能はget_string_ajax()リクエストごとの結果をキャッシュします。

この関数は非同期に動作するため、alert()およびconfirm()のコールには適していません。関数自体はユニークIDを含む<span>タグのプレースホルダを返します。プレースホルダはAJAXコールが戻った際に評価されたストリングと置換されます。そのため、あなたが直接alert()、confirm()またはその他の即時出力メソッドを使用する場合、ユーザには結果のストリングではなく、プレースホルダが表示されます。

<script type="text/javascript">
    // 正解! ページのHTMLに戻り値を挿入します
    var noresults = get_string_ajax('noresultsfound', 'mahara');
    jQuery('#notice').html('<p class="no-results">' + noresults + '</p>');

    // 不正解! あなたのユーザの警告ボックスに「<span id="str790709789087"></span>」が表示されます。
    alert(get_string_ajax('cannotremove', 'auth'));
</script>

言語ファイルの構造

言語ファイルは{section}.phpのように名前付けされます。ここでの「section」はセクション値としてget_string()に渡されます。これには「$string」と呼ばれる配列にキーを追加するための一連の行が含まれます。すべてのMaharaライブラリファイルのようにウェブブラウザからのアクセスを防ぐため、内部定数のチェックから始めてください。

<?php 
defined('INTERNAL') || die();

$string['changepassworddesc'] = '新しいパスワード';
$string['changepasswordotherinterface'] = 'あなたは異なるインターフェースでパスワードを変更できます。 ';
$string['oldpasswordincorrect'] = 'これはあなたの現在のパスワードではありません。';

// 複数形ストリングです。英語では単数形はキー「0」にマップしてください。他の言語ではlangconfig.php内のpluralfunctionで定義しているキーにマップしてください。
$string['updatednfiles'] = array(
    0 => 'あなたは %s ファイルを更新しました。',
    1 => 'あなたは %s ファイルを更新しました。',
);

複数形ストリング

正確には加算可能ストリングと読んだ方が良いのかもしれません。英語において2つの複数形があります: 単数形 (1つ) および複数形 (2つ以上)。他の言語には複数の複数形があります。例えばスロベニア語の場合、あなたが1つ、2つまたは3つ以上を持つかにより単語の末尾が異なる2通りの複数形があります。

英語とは異なる複数形を持つ言語を翻訳できるようにしたい場合、「あなたには 3 つのブログがあります/あなたには 1 つのブログがあります」のように数字でカウントできる特別な構文のストリングがあります。

まず、get_string()を使用する場合、第1カスタムパラメータとしてストリングのアイテムカウント数を渡してください:

get_string('fileattachedportfolioitems', 'artefact.file', $numitems);

次に言語ファイルでストリング配列を作成してください。英語の場合、キーが「0」の配列のアイテムは単数形のストリング、キーが「1」の配列のアイテムは複数形となります。

$string['fileattachedtoportfolioitems'] = array(
    0 => 'このファイルはあなたのポートフォリオの 1 の他のアイテムに添付されています。',
    1 => 'このファイルはあなたのポートフォリオの %s の他のアイテムに添付されています。',
);

この構文により、英語とは異なる複数形を持つ他の言語を実装できます。それぞれの言語にはどのキーがカウント数を返すか決定するpluralfunction関数を含むlangconfig.phpファイルがあります。英語は単数形に「0」、複数形に「1」を返します。恐らく、他の言語はさらに多くまたは少ないキーを返すと思われます。そのため、別の言語パックの同じストリングは以下のようになります:

$string['fileattachedtoportfolioitems'] = array(
    0 => 'Ta datoteka je pripeta k %s drugemu elementu v vašem listovniku.',
    1 => 'Ta datoteka je pripeta k %s drugima elementoma v vašem listovniku.',
    2 => 'Ta datoteka je pripeta k %s drugim elementom v vašem listovniku.',
    3 => 'Ta datoteka je pripeta k %s drugim elementom v vašem listovniku.',
);

詳細はLanguage Packs/Plural formsおよびhttps://bugs.launchpad.net/mahara/+bug/901051をご覧ください。

カウンタパラメータは最初のパラメータにしてください。あなたがカウンタパラメータをストリングの最初に表示したくない場合、sprintf位置指定子で移動にしてください:

$string['setprobationpoints'] = array(
    0 => 'Set probation points to %2$d for %1$d user.',
    1 => 'Set probation points to %2$d for %1$d users.';
);

メモ: Maharaにはこのフォーマットに従わない古い複数形ストリングが相当数含まれます。あなたが古い複数形ストリングを見つけた時に直してくれると助かります。翻訳者に分かりやすくするため、正しいストリングには古いストリングとは異なるストリング名を使用してください。あなたが古いストリングのすべての参照を削除できた場合のみ、古いストリングを削除してください。

Mahara言語ストリングはsprintf()フォーマットストリングです

私たちが「%s」をプレースホルダとして使用する理由はMahara言語ストリングが表示前にPHPのsprintf()関数で渡されるからです。言い換えれば、Mahara言語ストリングは実際にはsprintf()フォーマットストリングです!

詳細なsprintf()フォーマット文法はここで確認できますが、あなたが知る必要のある内容は以下の少しだけです:

直定数 "%" を "%%" としてエスケープする

言語ストリングにパーセンテージ文字 (%) を表示したい場合、あなたは代わりに2文字のパーセント (%%) でエスケープする必要があります。

$string['onehundredpercentcorrect'] = 'あなたは 100%% 正しい!';

あなたはほとんどのプレースホルダに「%s」を使用できます You can use "%s" for most placeholders

あなたがプレースホルダを使用した言語ストリングを記述している場合、多くの場合、sprintf()に値をストリングとしてフォーマットするように伝える「%s」で切り抜けられます。PHPはほとんどの値を適切にオートキャストします。

$string['mynameis'] = 'Hi, my name is %s!';

小数点のプレースホルダに関して ...  For decimal point number placeholders...

「%s」を使用する主な例外はプレースホルダに小数を表示する必要がある場合で特に小数点以下の数を表示する必要がある場合です。 この場合、あなたは「%」の後に「.」を続けて小数点以下を「F」にできます。

$string['twodecimalpoints'] = 'この数字には小数点以下2桁あります This number has two decimal points: %.2F';
$string['threedecimalpoints'] = 'この数字には小数点以下3桁あります This number has three decimal points: %.3F';

Although in many cases it may be less error-prone to just handle this on the PHP side of things. 多くの場合、これをPHP側のみで処理した方がエラーの発生は少ないように思えますが。That is, instead of passing a decimal number to get_string(), make your script round and/or format the number and cast it to a string, and then send that already-formatted number string to get_string().

言語ファイルはどこに? Where the lang files are

  • Core lang files live under $cfg->dirroot/lang/en.utf8/{section}.php
  • Plugin lang files live under $cfg->dirroot/{plugintype}/{pluginname}/lang/en.utf8/{plugintype}.{pluginname}.php
    • Note that the "section" for a plugin when invoking it in get_string(), is "{plugintype}.{pluginname}". For example: "artefact.blog", "import.leap2a", "blocktype.contactinfo"
    • Subplugins, such as a blocktype that belongs to an artefact, live under {$cfg->dirroot}/artefact/{pluginname}/blocktype/{blockname}/lang/en.utf8/blocktype.{blockname}.php and have "blocktype.{blockname}" as their section.
  • Theme lang files live under $cfg>->dirroot/theme/{themename}/lang/en.utf8/theme.{themename}.php
    • The "section" for a theme when invoking it in get_string(), is "theme.{themename}". For example: "theme.raw", "theme.primaryschool"
  • Foreign language langpacks are installed into your dataroot directory: $cfg->dataroot/langpacks/{langcode}
    • {langcode} will be the code for the language. For example "pt.utf8", "es.utf8", "en_US.utf8" etc
  • Local lang files live under $cfg->dirroot/local/lang/{langcode}/{section}.php

翻訳 Translations

The main point of this system is to allow for Mahara to be translated. See the "langpacks" documentation for more on that. Basically, you download a langpack from langpacks.mahara.org, unzip it, and put it in $cfg->dataroot/langpacks/. Then, users are presented with a language selection menu at the login screen.

If a particular lang string is not present in the langpack, then the English language string from Mahara core is used, unless the language specifies a parent language and the parent language's langpack is installed.

langconfig.php

Languages contain a small amount of configuration data. This goes in a "langconfig.php" core lang file. The following values are the most important:

  • thislanguage: The name of the language, in the language. This is displayed in the language selection menu that users see.
  • locale: A list of computer locale strings which this language matches. See the other lang packs for an idea of what these should look like.
  • parentlanguage: (Optional) If this is supplied, then for untranslated strings Mahara will attempt to find a translation in the parent language (if it's installed).
  • pluralization:
    • See the plural strings API.
    • For langpacks converted from PO Format, these values will be automatically generated if you include a "Plural-Forms:" header
    • pluralfunction: The name of a PHP function that will indicate which pluralization rule should be used for a given count. This function should take exactly one integer argument (the count of items) and will return a key which indicates which pluralization form should be used. For instance for English, the rule returns a "0" if the count is one, and a "1" if the count is anything else. All the lang files for the language will then define their plural strings as arrays, with a value for each possible key this function can return.
    • pluralrule: The Javascript equivalent of pluralfunction. This should be a snippet of Javascript that will evaluate an integer stored in the variable "n", and will return exactly the same value as the pluralfunction if it received n as its argument.

/localのカスタム言語ストリング

Custom lang strings in /local

Many Mahara installations may wish to overwrite only a few lang strings. The easiest way to do this is to create custom lang files under the /local directory. If present, the strings in these files will take priority over strings in the core lang files or langpack lang files.

Custom lang files don't need to translate 100% of the lang file they're over-riding. They can contain as few strings as you to care to actually override.

Example:

<?php
// This file lives under /var/www/mahara/local/lang/en.utf8/mahara.php
defined('INTERNAL') || die();

$string['yes'] = 'Yessir!';
$string['login'] = 'Sign in!";

You can place foreign language files, and plugin language files under local/lang as well. These are all acceptable:

  • local/lang/en.utf8/mahara.php
  • local/lang/en.utf8/blocktype.contactinfo.php
  • local/lang/pt.utf8/artefact.blog.php
  • local/lang/mi.utf8/theme.primaryschool.php

翻訳に連結は好ましくありません Concatenation is bad for translation

Because word orders are different in different languages, when possible you should avoid concatenating lang strings together. You should either use lang string parameters, or just use multiple language strings.

BAD:

<?php
// Works okay for English, but what about Spanish, where the adjective should follow the noun?
$yellowdogstr = get_string('yellow') . " " . get_string('dog');
$greendogstr = get_string('green') . " " . get_string('dog');

BETTER:

<?php
// English: $string['coloreddog'] = '%s dog';
// Spanish: $string['coloreddog'] = 'perro %s';
$yellowdogstr = get_string('coloreddog', 'artefact.dog', get_string('yellow'));
$greendogstr = get_string('coloreddog', 'artefact.dog', get_string('green'));

BEST:

<?php
// In some languages, the word for "dog" might change when it's paired with yellow, or the word
// for yellow might change when paired with dog
// English: $string['dogyellow'] = 'yellow dog';
// Spanish: $string['dogyellow'] = 'perro amarillo';
// Australian English: $string['dogyellow'] = 'dingo';
$yellowdogstr = get_string('dogyellow');
$greendogstr = get_string('doggreen');

And on a similar note, definitely don't concatenate word parts together.

BAD:

<?php
$blogstr = get_string('blog', 'artefact.blog');
$pluralblog = get_string('blog', 'artefact.blog') . get_string('s');

GOOD:

<?php
$blogstr = get_string('blog', 'artefact.blog');
$pluralblog = get_string('blogs', 'artefact.blog');

// Or if you've got a specific number of blogs, use the plural strings API
$numblogs = get_blog_count();
$blogstr = get_string('nblogs', 'artefact.blog', $numblogs);

This approach has the downside of leading to a proliferation of language strings, but unfortunately it's the only way to achieve clean translations among different languages with wildly different grammars.

あなたの言語ファイルをアルファベット順にする Alphabetize your lang files

From an implementation standpoint, it doesn't matter what order the lang strings are in, within a lang file. However, from a human-readability standpoint, they should be in alphabetical order by identifier.

Many developers are tempted to group them together by function, but any functional grouping scheme eventually falls apart as new strings are added which defy the classification scheme. The end result is a completely disordered file where any particular lang string could be in any place. This is how most of the lang files in Mahara core are.

So just go ahead and alphabetize the lang strings, when creating a new lang file. If you want to ensure that related strings wind up next to each other, give them names that classify them by type.

BAD:

<?php
// Strings are sorta grouped together by functionality, in semi-random order
$string['baseline'] = 'Baseline';
$string['top'] = 'Top';
$string['middle'] = 'Middle';
$string['bottom'] = 'Bottom';
$string['texttop'] = 'Text top';
$string['textbottom'] = 'Text bottom';
$string['left'] = 'Left';
$string['right'] = 'Right';
$string['src'] = 'Image URL';
$string['image_list'] = 'Attached image';
$string['alt'] = 'Description';

$string['copyfull'] = 'Others will get their own copy of your %s';
$string['copyreference'] = 'Others may display your %s in their page';
$string['copynocopy'] = 'Skip this block entirely when copying the page'; 

$string['viewposts'] = 'Copied entries (%s)';
$string['postscopiedfromview'] = 'Entries copied from %s'; 

$string['youhavenoblogs'] = 'You have no journals.';
$string['youhaveoneblog'] = 'You have 1 journal.';
$string['youhaveblogs'] = 'You have %s journals.';

GOOD:

<?php
// Strings are in alphabetical order by identifier
// Strings with similar purposes have names that start with their purpose and then a 
//    description, so that they wind up next to each other alphabetically
$string['copyfull'] = 'Others will get their own copy of your %s';
$string['copynocopy'] = 'Skip this block entirely when copying the page';
$string['copyreference'] = 'Others may display your %s in their page';
$string['imagealt'] = 'Description';
$string['imagelist'] = 'Attached image';
$string['imagesrc'] = 'Image URL';
$string['positionbaseline'] = 'Baseline';
$string['positionbottom'] = 'Bottom';
$string['positionleft'] = 'Left';
$string['positionmiddle'] = 'Middle';
$string['positionright'] = 'Right';
$string['positiontextbottom'] = 'Text bottom';
$string['positiontexttop'] = 'Text top';
$string['positiontop'] = 'Top';
$string['postscopiedfromview'] = 'Entries copied from %s';
$string['viewposts'] = 'Copied entries (%s)';
$string['youhaveblogs'] = 'You have %s journals.';
$string['youhavenoblogs'] = 'You have no journals.';
$string['youhaveoneblog'] = 'You have 1 journal.';

言語ストリング変更時に翻訳者に知らせる Let translators know when lang strings change

If you make a substantial change to the content of a lang string, you should also change the name of the lang string. Normally we do this by putting (or incrementing) a number after it.

The reason for this is because the Launchpad translation interface provides no notification to translators when the English version of a string has changed. Renaming the lang string will cause it to show up as a new, untranslated string, alerting translators to its presence.

BEFORE:

$string['namedesc'] = 'The original version of the string.';

AFTER:

$string['namedesc1'] = 'The new version of the string, with content that should be reflected in all langpacks.';

Be sure to also update the name of the string in the PHP files and templates where it is used.

ヘルプファイル Help files

Help files are a special type of lang file. They're HTML snippets (basically the contents within the <body> tag) which pop up when a user clicks on a help button.

They can be added in a few different ways. The main ones are:

Pieformsヘルプファイル Pieforms help files

They're most commonly created by adding the 'help'=>true to a pieform element definition. Pieforms will then automatically add code to pop up a help file named "help/forms/{formname}.{elementname}.html". If the form has a "pluginname" and "plugintype" field, Pieforms will look for the help file under the plugin's lang directory.

Example:

// The "draft" checkbox will have a helpfile located under
// artefact/blog/lang/en.utf8/help/form/editpost.draft.html
// because of the form's 'name', 'plugintype', 'pluginname', and the element's name.
$form = pieform(array(
    'name' => 'editpost',
    'plugintype' => 'artefact',
    'pluginname' => 'blog',
    'elements' => array(
         'draft' => array(
             'type' => 'checkbox',
             'title' => get_string('draft', 'artefact.blog'),
             'description' => get_string('thisisdrafdesc', 'artefact.blog'),
             'help' => true
         )
    )
);

ページヘルプファイル Page help files

A page itself can have a helpfile as well. If the page correctly defines the "SECTION_PAGE", "SECTION_PLUGINNAME", and "SECTION_PLUGINTYPE" constants, then smarty() on setting up the page template, will call the "has_help_file()" function, which checks for the presence of a help file under "help/pages/{SECTION_PAGE}.html". If present, it will print a help button next to the page title. If SECTION_PLUGINNAME and SECTION_PLUGINTYPE are provided, it will look for the help file under the plugin's lang directory.

Example:

<?php
// Help file will be artefact/blog/lang/en.utf8/help/page/view.html 
define('SECTION_PLUGINTYPE', 'artefact');
define('SECTION_PLUGINNAME', 'blog');
define('SECTION_PAGE', 'view');

See also Developer Area/Pagetop Constants

セクションヘルプファイル Section help files

Page sections can have help files. These live under "help/sections/" in the lang directory. They can be invoked by using the "contextualhelp" dwoo tag.

Example:

<!-- Help file will be lang/en.utf8/help/sections/activitytpeselect.html
     Note that it's under the core lang directory, because plugintype='core' -->
{contextualhelp plugintype='core' pluginname='activity' section='activitytypeselect'}

その他? Others?

TODO: Are the other ways to call up a help file? Will calling that function that generates the help icon do it?

localのカスタムヘルプファイル

Help files can also be overridden in the /local directory.

  • Core help files will go under local/lang/en.utf8/help/{forms|pages|sections}/{filename}.html
    • Example: local/lang/en.utf8/help/forms/adduser.friendscontrol.html
  • Plugin help files will go under /local/lang/en.utf8/help/{forms|pages|sections}/{plugintype}.{pluginname}.{filename}.html
    • Example: local/lang/en.utf8/help/forms/artefact.blog.addentry.draft.html

ストリングを変更できない場合のトラブルシューティング Troubleshooting strings that won't change

So, you're trying to change some language strings for development, or a local customization. You change the strings in the file, and reload the page, but the strings haven't changed. Here are some possible causes:

キャッシュ設定 Cached strings

Starting with Mahara 15.10, Mahara caches the navigation menus (which include several translated language strings) into the database. In Mahara 16.10 and up, you can use the "Clear caches" button on the admin screen, or the htdocs/admin/cli/clear_caches.php CLI script, to reset these cached strings.

In Mahara 15.10 and 16.04, the "Clear caches" button is not yet present. As a workaround, you can clear the cache by going to "Administration -> Site Configuration" and clicking the "Save changes" button at the bottom of the page. This will clear the cache whether or not you have actually made any changes. Alternately, you can trigger a cache clearing by bumping the version number in htdocs/local/version.php and running an upgrade.

ユーザデータフィールドにコピーされたデフォルトストリング Default strings copied into user data fields

Some language strings in Mahara are used as default values to copy into user-editable data fields. For instance, the text on "Administration -> Site pages" is generated from language strings, but is then stored in the database once admins edit it. In these cases, updating the original language string will not update the stored user data fields.

正しいストリングが見つかりませんでした Haven't found the right string

Some words and phrases appear in multiple language strings in different files. Double-check that you've found the right string in the right language file. Make sure to check plugin directories (like artefact/annotation/lang/en.utf8) as well as the core htdocs/lang directory.

ハードコードのストリング Hard-coded strings

It's a common bug for language strings to be hard-coded into PHP files or Dwoo templates, rather than moved into the lang files for translation. If nothing else manages to change a string, it may be worth looking outside the lang files to see if it has been mistakenly hard-coded.

If you find this happening in a file that is part of the Mahara standard distribution, please report it as a bug to the Mahara launchpad project. If you find this in a third-party plugin, please contact the plugin author.