Chapter on Internationalization and Localization #641

Merged
merged 7 commits into from Nov 14, 2016

Projects

None yet

7 participants

@igorsantos07
Contributor

Inclusion of material regarding pure i18n implementation, related to Gettext and Poedit.

Refs #623.

@igorsantos07
Contributor

I'm currently working on with LingoHub to get their approval for quotations and reference linking, as their article is a great resource for this subject but is copyrighted. Thus, some sections (such as key naming) were skipped until a decision is made by them.

@drbyte drbyte commented on an outdated diff Feb 16, 2016
_posts/05-06-01-Internationalization-and-Localization.md
+isChild: true
+anchor: i18n_l10n
+---
+
+## Internationalization (i18n) and Localization (l10n) {#i18n_l10n_title}
+
+_Disclaimer for newcomers: i18n and l10n are numeronyms, a kind of abbreviation where numbers are used to shorten
+words - in our case, internationalization becomes i18n and localization, l10n._
+
+First of all, we need to define those two similar concepts and other related things:
+
+- **Internationalization** is when you organize your code so it can be adapted to different languages or regions
+without refactors. This is usually done once - preferably, in the beginning of the project, or else you'll probably
+need some huge changes in the source!
+- **Localization** happens when you adapt the interface (mainly) by translating contents, based on the i18n work done
+before. It usually us done every time a new language or region needs support, and is updated when new interface pieces
@drbyte
drbyte Feb 16, 2016 Contributor

"It usually us done"

Should be "is", not "us"

@drbyte drbyte commented on an outdated diff Feb 16, 2016
_posts/05-06-01-Internationalization-and-Localization.md
+## Internationalization (i18n) and Localization (l10n) {#i18n_l10n_title}
+
+_Disclaimer for newcomers: i18n and l10n are numeronyms, a kind of abbreviation where numbers are used to shorten
+words - in our case, internationalization becomes i18n and localization, l10n._
+
+First of all, we need to define those two similar concepts and other related things:
+
+- **Internationalization** is when you organize your code so it can be adapted to different languages or regions
+without refactors. This is usually done once - preferably, in the beginning of the project, or else you'll probably
+need some huge changes in the source!
+- **Localization** happens when you adapt the interface (mainly) by translating contents, based on the i18n work done
+before. It usually us done every time a new language or region needs support, and is updated when new interface pieces
+are added, as they need to be available in all supported languages.
+- **Pluralization** defines the rules needed between different languages to interoperate strings containing numbers and
+counters. For instance, in English when you have only one item, it's singular, and anything different from that is
+called plural; plural is this language is indicated by adding an S after some words, and sometimes changes parts of it.
@drbyte
drbyte Feb 16, 2016 Contributor

; plural is this language is

should be "plural in this language is"

@drbyte drbyte commented on an outdated diff Feb 16, 2016
_posts/05-06-01-Internationalization-and-Localization.md
+
+### Structure
+
+#### Types of files
+There are three files you usually deal with while working with gettext. The main ones are PO (Portable Object) and
+MO (Machine Object) files, the first being a list of readable "translated objects" and the second, the corresponding
+binary to be interpreted by gettext when doing localization. There's also a POT (Template) file, that simply contains
+all existing keys from your source files, and can be used as a guide to generate and update all PO files. Those template
+files are not mandatory: depending on the tool you're using to do l10n, you can go just fine with only PO/MO files.
+You'll always have one pair of PO/MO files per language and region, but only one POT per domain.
+
+### Domains
+There are some cases, in big projects, where you might need to separate translations when the same words convey
+different meaning given a context. In those cases you split them into different _domains_. They're basically named
+groups of POT/PO/MO files, where the filename is the said _translation domain_. Small and medium-sized projects usually,
+for simplicity, use only one domain; it's name is arbitrary, but we will be using "main" for our code samples.
@drbyte
drbyte Feb 16, 2016 Contributor

it's name is arbitrary

In this case, it's should be its

@igorsantos07
Contributor

Thanks @drbyte, that's what happens when you write text after midnight :D
Fixed locally.

igorsantos07 added some commits Feb 15, 2016
@igorsantos07 igorsantos07 Adding basic explanation on i18n and section TODOs
- what's i18n, l10n and pluralization forms for
- common methods of implementation
- added the rest of the sub-sections, with TODOs
2032a64
@igorsantos07 igorsantos07 i18n: Adding info on extensions, files and folders 26b5607
@igorsantos07 igorsantos07 i18n: typos, keys, plurals and samples 844594e
@igorsantos07 igorsantos07 i18n: review and finishing post
- part about key types has been reviewed
- included the pieces about using Poedit, caching issues and usual helper functions
ca90db9
@igorsantos07 igorsantos07 referenced this pull request Feb 27, 2016
Closed

i18n and l10n #623

@petk petk commented on an outdated diff Feb 27, 2016
_posts/05-06-01-Internationalization-and-Localization.md
+bind_textdomain_codeset('main', 'UTF-8');
+
+// if your application has additional domains, as cited before, you should bind them here as well
+bindtextdomain('forum', '../locales');
+bind_textdomain_codeset('forum', 'UTF-8');
+
+// here we indicate the default domain the gettext() calls will respond to
+textdomain('main');
+
+// this would look for the string in forum.mo instead of main.mo
+// echo dgettext('forum', 'Welcome back!');
+?>
+{% endhighlight %}
+
+#### 3. Preparing translation for the first run
+To make matters easier - and one of the powerful advantages Gettext has over custom framework i18n packages - is it's custom file type. "Oh man, that's quite hard to understand and edit by hand, a simple array would be easier!" Make no mistake, applications like [Poedit] are here to help - _a lot_. You can get the program from [their website], it's free and available for all platforms. It's a pretty easy tool to get used to, and a very powerful one at the same time - using with responsability the powers Gettext gave it.
@petk
petk Feb 27, 2016 Contributor

responsability -> *responsibility

@drbyte drbyte commented on an outdated diff Feb 29, 2016
_posts/05-06-01-Internationalization-and-Localization.md
+the singular and plural version as `msgid` in English and their corresponding translations as `msgstr` 0 and 1
+(following the number given by the plural rule). There, string replacement is used as well so the number can be seen
+directly in the sentence, by using `%d`. The plural forms always have two `msgid` (singular and plural), so it's
+advised to not use a complex language as source of translation.
+
+### Discussion on l10n keys
+As you might have noticed, we're using as source ID the actual sentence in English. That `msgid` is the same used
+throughout all your `.po` files, meaning other languages will have the same format and the same `msgid` fields, but
+translated `msgstr` lines.
+
+Talking about translation keys, there are two main "schools" here:
+
+1. _`msgid` as a real sentence_.
+ The main advantage are:
+ - if there's pieces of the software untranslated in any given language, the key displayed will still maintain some
+ meaning. Example: if you happen to translate by heart from English to Spanish but needs help to translate to French,
@drbyte
drbyte Feb 29, 2016 Contributor

3 suggestions:

The main advantage advantages are:
- if there's there are pieces of the software untranslated in any given language, the key displayed will still maintain some
meaning. Example: if you happen to translate by heart from English to Spanish but needs need help to translate to French,

@drbyte drbyte commented on an outdated diff Feb 29, 2016
_posts/05-06-01-Internationalization-and-Localization.md
+ you might publish the new page with missing French sentences, and parts of the website would be displayed in English
+ instead;
+ - it's much easier for the translator to understand what's going on and make a proper translation based on the
+ `msgid`;
+ - it gives you "free" l10n for one language - the source one;
+ - The only disadvantage: if you need to change the actual text, you would need to replace the same `msgid`
+ across several language files.
+
+2. _`msgid` as a unique, structured key_. It would describe the sentence role in the application in a structured way,
+including the template or part where the string is located instead of its content.
+ - it's a great way to have the code organized, separating the text content from the template logic.
+ - however, that could bring problems to the translator that would miss the context. A source language file would be
+ needed as a basis for other translations. Example: the developer would ideally have an `en.po` file, that
+ translators would read to understand what to write in `fr.po` for instance.
+ - missing translations would display meaningless keys on screen (`TOP_MENU_WELCOME` instead of `Hello there, User!`
+ on the said untranslated French page). That's good as would force translation to be complete before publishing -
@drbyte
drbyte Feb 29, 2016 Contributor

insert it:

That's good as it would force translation to be complete

@drbyte drbyte commented on an outdated diff Feb 29, 2016
_posts/05-06-01-Internationalization-and-Localization.md
+including the template or part where the string is located instead of its content.
+ - it's a great way to have the code organized, separating the text content from the template logic.
+ - however, that could bring problems to the translator that would miss the context. A source language file would be
+ needed as a basis for other translations. Example: the developer would ideally have an `en.po` file, that
+ translators would read to understand what to write in `fr.po` for instance.
+ - missing translations would display meaningless keys on screen (`TOP_MENU_WELCOME` instead of `Hello there, User!`
+ on the said untranslated French page). That's good as would force translation to be complete before publishing -
+ but bad as translation issues would be really awful in the interface.
+
+The [Gettext manual][manual] favors the first approach, as in general it's easier for translators and users in
+case of trouble. That's how we will be working here as well.
+
+### Everyday usage
+In a common application, you would use some Gettext functions while writing static text in your pages. Those sentences
+would then appear in `.po` files, get translated, compiled into `.mo` files and then, used by Gettext when rendering
+the actual interface. Given that, let's tie together what we have discussed so far in a a step-by-step example:
@drbyte
drbyte Feb 29, 2016 Contributor

double a a:

discussed so far in a a step-by-step example:

@drbyte drbyte commented on an outdated diff Feb 29, 2016
_posts/05-06-01-Internationalization-and-Localization.md
+the actual interface. Given that, let's tie together what we have discussed so far in a a step-by-step example:
+
+#### 1. A sample template file, including some different gettext calls
+{% highlight php %}
+<?php include 'i18n_setup.php' ?>
+<div id="header">
+ <h1><?=sprintf(gettext('Welcome, %s!'), $name)?></h1>
+ <!-- code indented this way only for legibility here -->
+ <?php if ($unread): ?>
+ <h2><?=sprintf(
+ ngettext('Only one unread message',
+ '%d unread messages',
+ $unread),
+ $unread)?>
+ </h2>
+ <? endif ?>
@drbyte
drbyte Feb 29, 2016 Contributor

Given that you used <?php as your open tag earlier, I recommend also using it on your <? endif ?> line

@drbyte drbyte commented on an outdated diff Feb 29, 2016
_posts/05-06-01-Internationalization-and-Localization.md
+ <!-- code indented this way only for legibility here -->
+ <?php if ($unread): ?>
+ <h2><?=sprintf(
+ ngettext('Only one unread message',
+ '%d unread messages',
+ $unread),
+ $unread)?>
+ </h2>
+ <? endif ?>
+</div>
+
+<h1><?=gettext('Introduction')?></h1>
+<p><?=gettext('We\'re now translating some strings')?></p>
+{% endhighlight %}
+
+- [`gettext()`][func] simply translates a `msgid` into it's corresponding `msgstr` for a given language. There's also
@drbyte
drbyte Feb 29, 2016 Contributor

Remove the apostrophe in it's here:

into it's corresponding

@drbyte drbyte commented on an outdated diff Feb 29, 2016
_posts/05-06-01-Internationalization-and-Localization.md
+function valid($locale) {
+ return in_array($locale, ['en_US', 'en', 'pt_BR', 'pt', 'es_ES', 'es');
+}
+
+//setting the source/default locale, for informational purposes
+$lang = 'en_US';
+
+if (isset($_GET['lang']) && valid($_GET['lang'])) {
+ // the locale can be changed through the query-string
+ $lang = $_GET['lang']; //you should sanitize this!
+ setcookie('lang', $lang); //it's stored in a cookie so it can be reused
+} elseif (isset($_COOKIE['lang']) && valid($_COOKIE['lang'])) {
+ // if the cookie is present instead, let's just keep it
+ $lang = $_COOKIE['lang']; //you should sanitize this!
+} elseif (isset($_SERVER['HTTP_ACCEPT_LANGUAGE'])) {
+ // default resort: look for the languages the browser says the user accepts
@drbyte
drbyte Feb 29, 2016 Contributor

// default resort: look for the languages the browser says the user accepts

I'd recommend removing the word "resort", as it's not needed and in this context is used awkwardly.

@drbyte drbyte commented on an outdated diff Feb 29, 2016
_posts/05-06-01-Internationalization-and-Localization.md
+bind_textdomain_codeset('main', 'UTF-8');
+
+// if your application has additional domains, as cited before, you should bind them here as well
+bindtextdomain('forum', '../locales');
+bind_textdomain_codeset('forum', 'UTF-8');
+
+// here we indicate the default domain the gettext() calls will respond to
+textdomain('main');
+
+// this would look for the string in forum.mo instead of main.mo
+// echo dgettext('forum', 'Welcome back!');
+?>
+{% endhighlight %}
+
+#### 3. Preparing translation for the first run
+To make matters easier - and one of the powerful advantages Gettext has over custom framework i18n packages - is it's custom file type. "Oh man, that's quite hard to understand and edit by hand, a simple array would be easier!" Make no mistake, applications like [Poedit] are here to help - _a lot_. You can get the program from [their website], it's free and available for all platforms. It's a pretty easy tool to get used to, and a very powerful one at the same time - using with responsibility the powers Gettext gave it.
@drbyte
drbyte Feb 29, 2016 Contributor
  1. Another it's which should be its:

    is it's custom file type

  2. I suggest removing the last half of this sentence, as "using with responsibility the powers" is awkward wording, and I'm not sure this last phrase is needed to still convey the intended message:

    It's a pretty easy tool to get used to, and a very powerful one at the same time~ - using with responsibility the powers Gettext gave it~.

  3. The URL?

    from [their website]

@drbyte drbyte commented on an outdated diff Feb 29, 2016
_posts/05-06-01-Internationalization-and-Localization.md
+textdomain('main');
+
+// this would look for the string in forum.mo instead of main.mo
+// echo dgettext('forum', 'Welcome back!');
+?>
+{% endhighlight %}
+
+#### 3. Preparing translation for the first run
+To make matters easier - and one of the powerful advantages Gettext has over custom framework i18n packages - is it's custom file type. "Oh man, that's quite hard to understand and edit by hand, a simple array would be easier!" Make no mistake, applications like [Poedit] are here to help - _a lot_. You can get the program from [their website], it's free and available for all platforms. It's a pretty easy tool to get used to, and a very powerful one at the same time - using with responsibility the powers Gettext gave it.
+
+In the first run, you should select "File > New Catalog" from the menu. There you'll have a small screen where we will set the terrain so everything else runs smoothly. You'll be able to find those settings later through "Catalog > Properties":
+
+- Project name and version, Translation Team and email address: useful information that goes in the `.po` file header;
+- Language: here you should use that format we mentioned before, such as `en_US` or `pt_BR`;
+- Charsets: UTF-8, preferably;
+- Source charset: set here the charset used by your PHP files - probably UTF-8 AS well, right?
@drbyte
drbyte Feb 29, 2016 Contributor

probably UTF-8 AS well

Should AS well be as well ?

@drbyte drbyte commented on an outdated diff Feb 29, 2016
_posts/05-06-01-Internationalization-and-Localization.md
+To make matters easier - and one of the powerful advantages Gettext has over custom framework i18n packages - is it's custom file type. "Oh man, that's quite hard to understand and edit by hand, a simple array would be easier!" Make no mistake, applications like [Poedit] are here to help - _a lot_. You can get the program from [their website], it's free and available for all platforms. It's a pretty easy tool to get used to, and a very powerful one at the same time - using with responsibility the powers Gettext gave it.
+
+In the first run, you should select "File > New Catalog" from the menu. There you'll have a small screen where we will set the terrain so everything else runs smoothly. You'll be able to find those settings later through "Catalog > Properties":
+
+- Project name and version, Translation Team and email address: useful information that goes in the `.po` file header;
+- Language: here you should use that format we mentioned before, such as `en_US` or `pt_BR`;
+- Charsets: UTF-8, preferably;
+- Source charset: set here the charset used by your PHP files - probably UTF-8 AS well, right?
+- plural forms: here goes those rules we mentioned before - there's a link in there with samples as well;
+- Source paths: here you must include all folders from the project where `gettext()` (and siblings) will happen - this is usually your templates folder(s)
+- Source keywords: this last part is filled by default, but you might need to alter it later - and is one of the powerful points of Gettext. The underlying software knows how the `gettext()` calls look like in several programming languages, but you might as well create your own translation forms. This will be discussed later in the "Tips" section.
+
+After setting those points you'll be prompted to save the file - using that directory structure we mentioned as well, and then it will run a scan through your source files to find the localization calls. They'll be fed empty into the translation table, and you'll start typing in the localized versions of those strings. Save it and a `.mo` file will be (re)compiled into the same folder and ta-dah: your project is internationalized.
+
+#### 4. Translating strings
+As you may have noticed before, there are two main types of localized strings: simple ones and the ones with plural forms. The first ones have simply two boxes: source and localized string. The source string can't be modified as Gettext/Poedit do not include the powers to alter your source files - you should change the source itself and rescan the files. Tip: you may right-click a translation line and it will hint you with the source files and lines where that string is being.
@drbyte
drbyte Feb 29, 2016 Contributor

with the source files and lines where that string is being.

I think there's more to this sentence... ?

Or maybe just change being to found ?

@drbyte drbyte commented on an outdated diff Feb 29, 2016
_posts/05-06-01-Internationalization-and-Localization.md
+As you may have noticed before, there are two main types of localized strings: simple ones and the ones with plural forms. The first ones have simply two boxes: source and localized string. The source string can't be modified as Gettext/Poedit do not include the powers to alter your source files - you should change the source itself and rescan the files. Tip: you may right-click a translation line and it will hint you with the source files and lines where that string is being.
+On the other hand, plural form strings include two boxes to show the two source strings, and tabs so you can configure the different final forms.
+
+Whenever you change your sources and need to update the translations, just hit Refresh and Poedit will rescan the code, removing non-existent entries, merging the ones that changed and adding new ones. It may also try to guess some translations, based on other ones you did. Those guesses and the changed entries will receive a "Fuzzy" marker, indicating it needs review, being highlighted in the list. It's also useful if you have a translation team and someone tries to write something they're not sure about: just mark Fuzzy and someone else will review later.
+
+Finally, it's advised to leave "View > Untranslated entries first" marked, as it will help you _a lot_ to not forget any entry. From that menu you can also open parts of the UI that allow you to leave contextual information for translators, if needed.
+
+### Tips & Tricks
+
+#### Possible caching issues
+If you're running PHP as a module on Apache (`mod_php`), you might face issues with the `.mo` file being cached. It happens the first time it's read, and then, to update it, you might need to restart the server. On Nginx and PHP5 it usually takes only a couple of page refreshes to refresh the translation cache, and on PHP7 it is rarely needed.
+
+#### Additional helper functions
+As preferred by many people, it's easier to use `_()` instead of `gettext()`. Many custom i18n libraries from frameworks use something similar to `t()` as well, to make translated code shorter. However, that's the only function that sports a shortcut. You might want to add in your project some others, such as `__()` or `_n()` for `ngettext()`, or maybe a fancy `_r()` that would join `gettext()` and `sprintf()` calls.
+
+In those cases, you'll need to instruct the Gettext utility on how to extract the strings from those new functions. Don't be afraid, it's something very easy. It's just a field in the `.po` file, or a Settings screen on Poedit - remember when we mentioned it before? In the editor that option is inside "Catalog > Properties > Source keywords". You need to include there the specifications of those new functions, following [a specific format](func_format):
@drbyte
drbyte Feb 29, 2016 Contributor
  1. Don't need "something" here:

    Don't be afraid, it's something very easy.

    or even just:

    It's very easy.

  2. This "remember" phrase reflects a different tone from the rest of the document.

    It's just a field in the .po file, or a Settings screen on Poedit remember when we mentioned it before?

@drbyte drbyte commented on an outdated diff Feb 29, 2016
_posts/05-06-01-Internationalization-and-Localization.md
+Finally, it's advised to leave "View > Untranslated entries first" marked, as it will help you _a lot_ to not forget any entry. From that menu you can also open parts of the UI that allow you to leave contextual information for translators, if needed.
+
+### Tips & Tricks
+
+#### Possible caching issues
+If you're running PHP as a module on Apache (`mod_php`), you might face issues with the `.mo` file being cached. It happens the first time it's read, and then, to update it, you might need to restart the server. On Nginx and PHP5 it usually takes only a couple of page refreshes to refresh the translation cache, and on PHP7 it is rarely needed.
+
+#### Additional helper functions
+As preferred by many people, it's easier to use `_()` instead of `gettext()`. Many custom i18n libraries from frameworks use something similar to `t()` as well, to make translated code shorter. However, that's the only function that sports a shortcut. You might want to add in your project some others, such as `__()` or `_n()` for `ngettext()`, or maybe a fancy `_r()` that would join `gettext()` and `sprintf()` calls.
+
+In those cases, you'll need to instruct the Gettext utility on how to extract the strings from those new functions. Don't be afraid, it's something very easy. It's just a field in the `.po` file, or a Settings screen on Poedit - remember when we mentioned it before? In the editor that option is inside "Catalog > Properties > Source keywords". You need to include there the specifications of those new functions, following [a specific format](func_format):
+
+- if you create something like `t()` that simply returns the translation for a string, you can specify it as `t`. Gettext will know the only function argument is the string to be translated;
+- if the function has more than one argument, you can specify in which one the first string is - and if needed, the plural form as well. For instance, if we call our function like this: `__('one user', '%d users', $number)`, the specification would be `__:1,2`, meaning the first form is the first argument, and the second form is the second argument. If your number comes as first argument instead, the spec would be `__:2,3`, indicating the first form is the second argument, and so on.
+
+After including those new rules in the `.po` file, a new scan will bring your new strings just as easy as before.
@drbyte
drbyte Feb 29, 2016 Contributor

will bring your new strings

When you say bring, do you mean bring in? Or would it be more specific to say index?

@igorsantos07
Contributor

@drbyte thanks for all that effort on reviewing :)
Besides not being native, I've been writing that during late night, not the most attentive part of my day 😅

@drbyte
Contributor
drbyte commented Feb 29, 2016

Besides not being native, I've been writing that during late night, not the most attentive part of my day

Hey, for “not being native”, your command of English is good! :)

@philsturgeon
Collaborator

@drbyte You speak better English than I speak Portugese that's for sure. I've been trying to learn Spanish for a year and I'm just about good enough to get through a meal, and have a few useless bastard phrases boiled into my head like "No es un huevo, es un manzana!"

I have much respect for anyone contributing in a language other than their first. Hopefully you weren't be embarrassed somebody pointed out the typos and tweaks, it's all part of the process. :)

@drbyte
Contributor
drbyte commented Feb 29, 2016

Agreed @philsturgeon . I've huge respect for what @igorsantos07 has contributed, particularly writing in non-native language.

And, I've learned some stuff about gettext that I didn't know before too :)

@igorsantos07
Contributor

@drbyte that's for sure what makes me happy :D

Regarding get embarrassed, those where mostly typos and result of a lack of attention, at most. I would get if I had written uninteligible babble hahahaha

@igorsantos07
Contributor

@codeguy any news on this? :)

@igorsantos07
Contributor

@codeguy was this forgotten? :(

@drbyte
Contributor
drbyte commented Jul 19, 2016

When I last reviewed it, my opinion was 👍
Hopefully it will get merged.

@philsturgeon
Collaborator

It's got a +1 from me. I threw this out on Twitter to see if there is any further feedback, and if nothing has happened in 24 hours I'll click that shiny green button.

@heiglandreas heiglandreas and 3 others commented on an outdated diff Jul 19, 2016
_posts/05-06-01-Internationalization-and-Localization.md
+languages with a total of four, five or six forms, such as Slovenian, Irish or Arabic.
+
+## Common ways to implement
+The easiest way to internationalize PHP software is by using array files and using those strings in templates, such as
+`<h1><?=$TRANS['title_about_page']?></h1>`. This is, however, hardly a recommended way for serious projects, as it poses
+some maintenance issues along the road - some might appear in the very beginning, such as pluralization. So, please,
+don't try this if your project will contain more than a couple of pages.
+
+Some frameworks will sport their own i18n packages. Those usually are a more powerful version of the above approach,
+but including features needed for real localization, such as plural forms and string replacement. You're free to use
+those if you feel like, but you might find bothering to edit array source files, having to deal with pure code issues
+(such as string scaping and so on). The main pro here is integration with the environment you're using - the framework
+is called _full-stack_ for a reason, right?
+
+However, the most classic way and often taken as reference for i18n and l10n is a [Unix tool called `gettext`][gettext].
+It dates back to 1995 and is still the most complete implementation for translating software. It is pretty easy to get
@heiglandreas
heiglandreas Jul 19, 2016 Contributor

Personally I'd favour mentioning of other tools here that might be used by professional translators (which, as far as I know, gettext usually isn't) for example XLIFF.

@philsturgeon
philsturgeon Jul 19, 2016 Collaborator

I'm always a fan to add more relevant tools and alternatives in, even if they're not the most popular. Maybe if theres a Composer-based one floating around that'll help those unable to install extensions and the like too.

@philsturgeon
philsturgeon Jul 20, 2016 Collaborator

Sure!

@igorsantos07
igorsantos07 Jul 20, 2016 Contributor

ok, just to make sure I got it right. What's missing is citing some sort of library like this (awesomely giant) Gettext?
I liked the idea, it's a great addition :)

@philsturgeon
philsturgeon Jul 20, 2016 Collaborator

Yeah, generally we don't just have one tool, we put a few decent options in so people can find the right thing. So a user and gettext and maybe a popular alternative would be two good additions to what you have. If you know of any!

Phil Sturgeon
Sent from my iPhone and there's probably typos because I'm probably at the pub.

On Jul 20, 2016, at 16:29, Igor Santos notifications@github.com wrote:

In _posts/05-06-01-Internationalization-and-Localization.md:

+languages with a total of four, five or six forms, such as Slovenian, Irish or Arabic.
+
+## Common ways to implement
+The easiest way to internationalize PHP software is by using array files and using those strings in templates, such as
+<h1><?=$TRANS['title_about_page']?></h1>. This is, however, hardly a recommended way for serious projects, as it poses
+some maintenance issues along the road - some might appear in the very beginning, such as pluralization. So, please,
+don't try this if your project will contain more than a couple of pages.
+
+Some frameworks will sport their own i18n packages. Those usually are a more powerful version of the above approach,
+but including features needed for real localization, such as plural forms and string replacement. You're free to use
+those if you feel like, but you might find bothering to edit array source files, having to deal with pure code issues
+(such as string scaping and so on). The main pro here is integration with the environment you're using - the framework
+is called full-stack for a reason, right?
+
+However, the most classic way and often taken as reference for i18n and l10n is a [Unix tool called gettext][gettext].
+It dates back to 1995 and is still the most complete implementation for translating software. It is pretty easy to get
ok, just to make sure I got it right. What's missing is citing some sort of library like this (awesomely giant) Gettext?
I liked the idea, it's a great addition :)


You are receiving this because you were mentioned.
Reply to this email directly, view it on GitHub, or mute the thread.

@localheinz
localheinz Jul 20, 2016 Contributor

@igorsantos07 @philsturgeon

Updated the list above!

@philsturgeon
philsturgeon Jul 21, 2016 Collaborator

Cool, work that into the PR and I'll get merging. :)

@igorsantos07
igorsantos07 Nov 13, 2016 edited Contributor

Uh-oh. It seems I had forgotten the suggestions here, made by @heiglandreas and @localheinz. Worked on those already!

@codeguy
Owner
codeguy commented Jul 19, 2016

+1 from me. @philsturgeon if this is ready to merge with no more feedback, go ahead and merge.

@igorsantos07
Contributor

@codeguy, @philsturgeon: I added the forgotten suggestions and also checked the text for a couple of more subtle grammar mistakes :)

I think it's now finally ready? Almost a year taking dust, sorry for making this even longer.

@philsturgeon philsturgeon merged commit 42fa3bf into codeguy:gh-pages Nov 14, 2016
@philsturgeon
Collaborator

Great work @igorsantos07! Thank you for following through on the requested changes. FOSS is not always speedy, but the willingness to keep at it is appreciated.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment