Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add https://wiki.phpbb.com/Plural_Rules to doc #20

Merged
merged 3 commits into from
May 29, 2015
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
1 change: 1 addition & 0 deletions development/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ Contents:
:maxdepth: 2

development/coding_guidelines
language/index
update/index


Expand Down
8 changes: 8 additions & 0 deletions development/language/index.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
Languages and translations
==========================

.. toctree::
:maxdepth: 2

plurals
usage
219 changes: 219 additions & 0 deletions development/language/plurals.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,219 @@
=======
Plurals
=======

Short Example
=============

The english language is very simple when it comes to plurals:

*You have 0 elephants, 1 elephant, or 2+ elephants.*

So basically you have 2 different forms: one singular and one plural.


But for some other languages this is quite a bit more difficult. Let's take
the Bosnian language as another example:

*You have [1/21/31] slon, [2/3/4] slona, [0/5/6] slonova and [7/8/9/11] ...*

The problem with the old system of plurals was that you would have needed to
specify them all, and get a loop in there.


As we are not the first developers facing this problem, it was not really hard
to find a suitable solution. We decided to use the system from
`Mozilla <https://developer.mozilla.org/en/Localization_and_Plurals>`_.

Plural Rules
============
So we defined the following 16 rules for plurals. First point is the language
family, afterwards there are a number of rows with the following format:
**<key> - <rule>: <example-numbers>**

**Note:** 0 is handled as a special case. If you add a key 0 to your
array, that will be used in case of 0 independent of the plural rule.

Rule #0
-------
* Families: Asian (Chinese, Japanese, Korean, Vietnamese), Persian, Turkic/Altaic (Turkish), Thai, Lao
* 1 - everything: 0, 1, 2, ...

Rule #1
-------
* Families: Germanic (Danish, Dutch, English, Faroese, Frisian, German, Norwegian, Swedish),
Finno-Ugric (Estonian, Finnish, Hungarian), Language isolate (Basque), Latin/Greek (Greek),
Semitic (Hebrew), Romanic (Italian, Portuguese, Spanish, Catalan)
* 1 - 1
* 2 - everything else: 0, 2, 3, ...

Rule #2
-------
* Families: Romanic (French, Portuguese, Brazilian Portuguese)
* 1 - 0, 1
* 2 - everything else: 2, 3, ...

Rule #3
-------
* Families: Baltic (Latvian)
* 1 - 0
* 2 - ends in 1, excluding 11: 1, 21, ... 101, 121, ...
* 3 - everything else: 2, 3, ... 10, 11, 12, ... 20, 22, ...

Rule #4
-------
* Families: Celtic (Scottish Gaelic)
* 1 - is 1 or 11: 1, 11
* 2 - is 2 or 12: 2, 12
* 3 - others between 3 and 19: 3, 4, ... 10, 13, ... 18, 19
* 4 - everything else: 0, 20, 21, ...

Rule #5
-------
* Families: Romanic (Romanian)
* 1 - 1
* 2 - is 0 or ends in 01-19, excluding 1: 0, 2, 3, ... 19, 101, 102, ... 119, 201, ...
* 3 - everything else: 20, 21, ...

Rule #6
-------
* Families: Baltic (Lithuanian)
* 1 - ends in 1, excluding 11: 1, 21, 31, ... 101, 121, ...
* 2 - ends in 0 or ends in 10-20: 0, 10, 11, 12, ... 19, 20, 30, 40, ...
* 3 - everything else: 2, 3, ... 8, 9, 22, 23, ... 29, 32, 33, ...

Rule #7
-------
* Families: Slavic (Bosnian, Croatian, Serbian, Russian, Ukrainian)
* 1 - ends in 1, excluding 11: 1, 21, 31, ... 101, 121, ...
* 2 - ends in 2-4, excluding 12-14: 2, 3, 4, 22, 23, 24, 32, ...
* 3 - everything else: 0, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 25, 26, ...

Rule #8
-------
* Families: Slavic (Slovak, Czech)
* 1 - 1
* 2 - 2, 3, 4
* 3 - everything else: 0, 5, 6, 7, ...

Rule #9
-------
* Families: Slavic (Polish)
* 1 - 1
* 2 - ends in 2-4, excluding 12-14: 2, 3, 4, 22, 23, 24, 32, ... 104, 122, ...
* 3 - everything else: 0, 5, 6, ... 11, 12, 13, 14, 15, ... 20, 21, 25, ...

Rule #10
--------
* Families: Slavic (Slovenian, Sorbian)
* 1 - ends in 01: 1, 101, 201, ...
* 2 - ends in 02: 2, 102, 202, ...
* 3 - ends in 03-04: 3, 4, 103, 104, 203, 204, ...
* 4 - everything else: 0, 5, 6, 7, 8, 9, 10, 11, ...

Rule #11
--------
* Families: Celtic (Irish Gaeilge)
* 1 - 1
* 2 - 2
* 3 - is 3-6: 3, 4, 5, 6
* 4 - is 7-10: 7, 8, 9, 10
* 5 - everything else: 0, 11, 12, ...

Rule #12
--------
* Families: Semitic (Arabic)
* 1 - 1
* 2 - 2
* 3 - ends in 03-10: 3, 4, ... 10, 103, 104, ... 110, 203, 204, ...
* 4 - ends in 11-99: 11, ... 99, 111, 112, ...
* 5 - everything else: 100, 101, 102, 200, 201, 202, ...
* 6 - 0

Rule #13
--------
* Families: Semitic (Maltese)
* 1 - 1
* 2 - ends in 01-10: 0, 2, 3, ... 9, 10, 101, 102, ...
* 3 - ends in 11-19: 11, 12, ... 18, 19, 111, 112, ...
* 4 - everything else: 20, 21, ...

Rule #14
--------
* Families: Slavic (Macedonian)
* 1 - ends in 1: 1, 11, 21, ...
* 2 - ends in 2: 2, 12, 22, ...
* 3 - everything else: 0, 3, 4, ... 10, 13, 14, ... 20, 23, ...

Rule #15
--------
* Families: Icelandic
* 1 - ends in 1, excluding 11: 1, 21, 31, ... 101, 121, 131, ...
* 2 - everything else: 0, 2, 3, ... 10, 11, 12, ... 20, 22, ...

How to use the rules
====================
The first thing your language package needs, is a definition, which rule to
use for your package. This is done in the ``language/xy/common.php`` language
file at the beginning of the array, (Rule #1 is the rule for the English
language and will be used by default, if you don't specify one):

.. code-block:: php

'PLURAL_RULE' => 1,

The following example is using rule **#13**:

It has the following rows:

* 1 - 1
* 2 - ends in 01-10: 2, 3, ... 9, 10, 101, 102, ...
* 3 - ends in 11-19: 11, 12, ... 18, 19, 111, 112, ...
* 4 - everything else: 20, 21, ...

While the English language only has 2 rows in its array:

.. code-block:: php

'EXAMPLE' => array(
1 => '1 example',
2 => '2 or more examples',
),

You need to specify the zero-row and 4 rows for the "plurals":

.. code-block:: php

'EXAMPLE' => array(
1 => '1 example',
2 => '[0 or number ending with 01-10] examples',
3 => '[number ending with 11-19] example',
4 => 'even more examples',
),

If you require separate handling for 0, you can simple add the 0-case:

.. code-block:: php

'EXAMPLE' => array(
0 => 'No example',
1 => '1 example',
2 => '[zero is not handled here anymore! Only number ending with 01-10] examples',
3 => '[number ending with 11-19] example',
4 => 'even more examples',
),

If you forget a line the system will automatically use the row before. So if
you forget to add the *3*-row, it will use *2*-row for 11-19 as well. If there
is no previous row, it uses the last row of the array.


**Ensure your cases are in ascending order**, otherwise the system may produce
unexpected results if any keys are missing or out of order.

Credits
=======
The system is based on
`Mozilla <https://developer.mozilla.org/en/Localization_and_Plurals>`_, which
uses the "Plural Rules and Families" from
`GNU gettext documentation <http://www.gnu.org/software/gettext/manual/html_node/gettext_150.html#Plural-forms>`_.
116 changes: 116 additions & 0 deletions development/language/usage.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,116 @@
=========================
Using the Language System
=========================

phpBB uses a language system to guarantee easy localisation. All strings
presented to the user are first looked up in an internal dictionary. Thus it is
also a requirement for Extensions to use said system for all output presented to
the user. This chapter will show you how to use the language system and how to
add your custom entries.


Using the Language System in php
================================

The object holding the language dictionary for the current user is - hardly
surprising - the ``$user`` object. We generally refer to the name of the word in
the dictionary as **language key**, to the returned value as **language string**
or **language value**. Both together are a **language entry**. By convention,
the language key should always be all-uppercase. Language entries are collected
in language files.

To lookup a language entry inside of phpBB, query the ``$user`` object like
this: ``$user->lang('LANG_KEY')``, which will return the language string
assigned to the key ``LANG_KEY`` in the current user's language. Note that many
functions in phpBB automatically translate their arguments; passing the language
key as an argument is usually enough.

The dictionary is not loaded into memory all at once, but is split up in several
files, which have to be manually loaded on demand. The files are stored inside
the language directory, named after its
`language tag <https://area51.phpbb.com/docs/30x/coding-guidelines.html#translation>`_,
where one subdirectory is used for each installed language. The default language
files are in the root of that subdirectory, while ACP language files go into the
``/acp`` subdirectory; email templates are placed in the ``/email``
subdirectory. Files for extensions should be placed in the extension's
``/language`` directory.

Additional language files can be loaded during user setup via the call to the
``$user->setup()`` method at the top of each accessible file. To do so, pass the
name with the subdirectory but without extension as argument of setup. For
instance ``$user->setup('search')`` or ``$user->setup('mylangfile')`` or
``$user->setup(array('mylangfile', 'search'))``. If you need to add a language
file at a later stage, use add_lang, e.g.
``$user->add_lang(array('mylangfile', 'search'))``.

A sightly more difficult situation arises when the displayed text should contain
links etc. phpBB uses a ``lang()``-method for that, for instance:

.. code-block:: php

$message .= '<br /><br />' . $user->lang('MY_TRICKY_LANGUAGE_KEY', '<a href="' . append_sid("{$phpbb_root_path}mypage.$phpEx") . '">', '</a>');
trigger_error($message);

Using the Language System in template files
===========================================

Language entries in
`Using the Template System <https://wiki.phpbb.com/Using_the_phpBB3.0_Template_System>`_
are a major improvement since phpBB 3.0. There is no longer a need to manually
assign these in the php file; loaded language files will be automatically used.
To use the language entry with the key ``MY_KEY`` in a template file, just write
``{L_MY_KEY}`` in the template - it's as simple as that.

Add new entries
===============

New language files should always be placed in their own files in the extensions
directory. There are however a few exceptions, notably log entries and module
names. Those need to be placed in their appropriate common.php language file,
either in the language's directory or the acp subdirectory.

**Note:** When writing or editing a language file, make sure to save it using
utf-8 encoding **without BOM**
(`Byte Order Mark <http://en.wikipedia.org/wiki/Byte_Order_Mark>`_). Otherwise
the forum will not function properly. Some editors call that mode "utf8 cookie".

.. code-block:: php

<?php
/**
*
* This file is part of the phpBB Forum Software package.
*
* @copyright (c) phpBB Limited <https://www.phpbb.com>
* @license GNU General Public License, version 2 (GPL-2.0)
*
* For full copyright and license information, please see
* the docs/CREDITS.txt file.
*
*/

/**
* DO NOT CHANGE
*/
if (empty($lang) || !is_array($lang))
{
$lang = array();
}

// DEVELOPERS PLEASE NOTE
//
// All language files should use UTF-8 as their encoding and the files must not contain a BOM.
//
// Placeholders can now contain order information, e.g. instead of
// 'Page %s of %s' you can (and should) write 'Page %1$s of %2$s', this allows
// translators to re-order the output of data while ensuring it remains correct
//
// You do not need this where single placeholders are used, e.g. 'Message %d' is fine
// equally where a string contains only two placeholders which are used to wrap text
// in a url you again do not need to specify an order e.g., 'Click %sHERE%s' is fine

$lang = array_merge($lang, array(
'MY_LANGUAGE_KEY' => 'A language entry',
'MY_OTHER_LANGUAGE_KEY' => 'Another language entry',
'MY_TRICKY_LANGUAGE_KEY' => 'This is a %slink%s',
));