Thread Rating:
  • 0 Vote(s) - 0 Average
  • 1
  • 2
  • 3
  • 4
  • 5
unified directory for plugin translation files
#1
I found out that managing and updating plugins translation file became a bit of a hassle.
Some plugins don't contain a translation file (english only by default ), and other one may contain even 2 translation files spread across /plugins/plugin_name directory.

What I'd like to say is that GS should get a dedicated directory for plugins translation files
it may be even /plugins/lang
and translation files should be created with pattern: [plugin_name]_[language]
for example:/plugins/lang/i18n_navigation_de_DE

With such solution I would still be able to have old translation file, although it wouldn't contain all translated phrases, but I would noticed it in admin panel, and upgrade it.

Maybe some sort of alert window, with information that existing translation file need upgrade, would be nice.
But this is more a request to plugin developers, to checkout if all translation vars exist and if not, show an alert.
It could be just by using a version variable and compare it once after installation.
Addons: blue business theme, Online Visitors, Notepad
Reply
#2
that is a great idea, I support that (being a permanent translator of badly documented plugins (CMSMadeSimple for example)
|--

Das deutschsprachige GetSimple-(Unter-)Forum:   http://get-simple.info/forums/forumdisplay.php?fid=18
Reply
#3
The problem is that each plugin has to handle translations itself.
Thus the GetSimple core should provide a function load_i18n($name, $language, $default_language),
  • where $name is the plugin name, e.g. "i18n_navigation"
  • where $language by default equals the global $LANG (administration language),
  • where $default_language by default is en_US,
  • and the function tries to load the translation from the full language file - if it exists - e.g. "/plugins/lang/i18n_navigation_de_DE.php" as "i18n_navigation/".key = value,
  • loads all additional translations from the language only file - if it exists - e.g. "/plugins/lang/i18n_navigation_de.php"
  • loads all additional translations from the full default language file, e.g. "/plugins/lang/i18n_navigation_en_US.php"
  • the format of the language files is the same as for GetSimple itself (keys without plugin prefix)
  • all translations can be accessed by the functions i18n and i18n_r, e.g. i18n_r("i18n_navigation/PAGES")

This way the translations other than the default language do not need to be complete - the default language is used if a translation is missing.

Important are the language parameters for the load_i18n function as they are different whether the function is called for a admin or frontend functionality (e.g. load_i18n("i18n_search", $language, I18N_DEFAULT_LANGUAGE) when using the I18N plugin for the frontend)

E.g. file /plugins/lang/18n_navigation_de_DE.php:
Code:
<?php
$i18n = array(
  'NAVIGATION' => 'Navigationsstruktur bearbeiten (I18N)',
  'TOP' => 'am Anfang',
  'INSERT_AFTER' => 'einfügen nach'
);
when loaded with load_i18n("i18n_navigation") and then called with i18n_r("i18n_navigation/TOP") will yield "am Anfang".
I18N, I18N Search, I18N Gallery, I18N Special Pages - essential plugins for multi-language sites.
Reply
#4
I see the problems here - but i'm not sure this is the best way to handle it. It looks a little complicated - and it also completely depends on the plugin developers internationalizing their plugins the correct way to begin with.

I think it's far simpler to have the plugin developer do their own translation files (maybe with a "how-to correctly make your plugin translatable" within our wiki so it's standardized) . Then along with the "support forum" link within Extend, other people could upload/share their translation files.

@mvlcek - Please feel free to draw up standards how plugin developers should handle translations within their own plugins and add it to the wiki. I think we can make this work without a huge ordeal within the backend core managing all these plugin language files.

Hopefully that made sense, but i think creating a whole system around translating plugin files is a little bit out of GetSimple's scope.
- Chris
Thanks for using GetSimple! - Download

Please do not email me directly for help regarding GetSimple. Please post all your questions/problems in the forum!
Reply
#5
As I'm currently consolidating my plugins and making them translateable, I've created common functions which provide the above functionality - not fully tested yet:

Code:
<?php
// these functions should be in the GetSimple Core:
if (!function_exists('is_admin')) {
  function is_admin() {
    return basename($_SERVER['PHP_SELF']) != 'index.php';
  }
}

if (!function_exists('load_i18n')) {

  $i18n_plugins_loaded = array();  

  function load_i18n($plugin, $language=null, $default_language=null) {
    global $i18n, $LANG, $i18n_plugins_loaded;
    if (in_array($plugin, $i18n_plugins_loaded)) return;
    if (!$language) $language = $LANG;
    if (!$default_language) $default_language = 'en_US';
    $langs = array($language);
    $pos = strpos($language,'_');
    if ($pos !== false) {
      $lang = substr($language, 0, $pos);
      if (!in_array($lang, $langs)) $langs[] = $lang;
    }
    if (!in_array($default_language, $langs)) $langs[] = $default_language;
    foreach ($langs as $lang) load_i18n_impl($plugin, $lang, $i18n);
    $i18n_plugins_loaded[] = $plugin;
  }

  function load_i18n_impl($plugin, $lang, &$globali18n) {
    $i18n = array();
    //@include(GSPLUGINPATH.'lang/'.$plugin.'_'.$lang.'.php');
    @include(GSPLUGINPATH.$plugin.'/lang/'.$lang.'.php');
    if (count($i18n) > 0) foreach ($i18n as $code => $text) {
      if (!array_key_exists($plugin.'/'.$code, $globali18n)) $globali18n[$plugin.'/'.$code] = $text;
    }
  }
}

I think these functions should be included in the Core. They can be used, if the plugin developer adheres to the standards - here the language files are expected in plugins/<plugin>/lang/<lang>.php (but that can be changed).

BTW: Is there a reason to have translation files as code as opposed to property files (like standard for Java)?

Code:
PAGES=View Pages
DELETE_PAGE=Delete this page
I18N, I18N Search, I18N Gallery, I18N Special Pages - essential plugins for multi-language sites.
Reply
#6
mvlcek: but still you are talking about lang directory inside plugin folder dir, and I had on my mind a unified directory only for lang files.
I thought a bit about it and /plugins/lang/ dir with plugin_name_language files may get a bit messed up pretty fast, so /plugins/lang/plugin_name/language_files is a bit better idea.

CC: I noticed that some plugins would be fine with translation variables provided in language files for GS.
Having this on mind what do you think about adding to http://get-simple.info/wiki/plugins:creation a list of basic translation variables, so plugin devs could just use them and their translations would be handled by lang file for GS automatically.
Rest of needed vars would have to be placed in stand alone translation file.

edit: at least encourage plugin devs to use vars already used by GS
Addons: blue business theme, Online Visitors, Notepad
Reply
#7
@yojoe - good idea. Much simpler than ( no offense meant ) mvlcek's suggestion. Anything more I think we just need a good structure for how a plugin can offer translations. If no one is willing to write a wiki article, I can try and draw something up later.
- Chris
Thanks for using GetSimple! - Download

Please do not email me directly for help regarding GetSimple. Please post all your questions/problems in the forum!
Reply
#8
I was thinking also about a possibility to upload translation files directly into plugin's archives in extend.
(the backend would have to compress all plugin files along with translation files before it would be send to visitor who requested the file)

But there are 2 major problems with it:
1. what if plugin developer uploads a new version of his plugin ?
2. what if somebody creates own version of translation file for a plugin, and uploads it ?

As it goes about first point, traductors could be informed through a mail, that there's a new version of plugin which needs a translation update.

With second point, plugin dev would have to have a possibility to manage incoming translation files. It's a bit complex, as developer would have to have the ability to manage all actions in all possible circumstances.
But then we step into another problem: if developer stops development, and forgets about GS completely, but his plugins will be still working in new GS versions, who will handle uploaded translation files ?
Addons: blue business theme, Online Visitors, Notepad
Reply
#9
@yojoe: whether the files are stored as plugins/<plugin>_<lang>.php or plugins/lang/<plugin>/<lang>.php or plugins/<plugin>/lang/<lang>.php doesn't matter from a technical POV (in the latter case it's just easiest to identify the files for a plugin, simply <plugin>.php and the <plugin> directory). I'm happy with any standard.

I agree, as long it's possible using GetSimple translations is best to have consistent texts.

@ccagle: yojoe's suggestion is to standardize how the translations should be organized, which I totally approve of. From a developer's POV missing is, how to access these translations. That's where I suggested to standardize this by adding the above functions to the Core.

The developer just supplies the translation files (with the help of the community - handling see yojoe's suggestions) and then uses the following code:

Code:
load_i18n('myplugin');
// or alternatively load_i18n('myplugin', $language_from_my_configuration, $my_default_language);
...
i18n('PAGES'); // accessing standard GetSimple text
i18n('myplugin/MYTEXT'); // accessing plugin specific text

If we don't put this functionality into the Core, every developer has to copy or reimplement a similar function.
If this functionality is in the Core and the standards are described, he/she can't say "It's too complex - maybe later..."

BTW: I am willing to write the technical part of the wiki article. In the meantime let's try to figure out, how the process of providing translations should look like.
I18N, I18N Search, I18N Gallery, I18N Special Pages - essential plugins for multi-language sites.
Reply
#10
ok, I was thinking of this a lot last night and came up with an idea. I think it's a good middle between too complex (mvlcek's original idea) and the nothing we have right now.

What if we do this:
  • Allow developers to create their own folder within their plugin structure like this: '/myplugin-folder/lang/'
  • Give them a function that allows them to "merge" their language file (which is an array just like before) with the site-wide language file. Something like this: i18n_merge('../path-to-my-plugin/lang/en_US.php');

Then the developers could use their own translations and the default language file translations (the ones that yojoe talked about here) using the same exact methods as the rest of GetSimple: i18n('TAG') or i18n_r('TAG')

I would leave it up to the developers to decide how they want to handle switching languages within their plugins:
  • Maybe the plugin language file is always called language.php, and the user just replaces that file with their own language.php. I see no problem with this because once a language is set within the installation, its not going to change 99.9% of the time.
  • Or maybe the plugins write a control panel form that allows people to switch between installed language files.

... I don't think I should dictate that part of the process. I just want to give the developers a simple and standard way to internationalize their plugins, and i think this fits the bill.
- Chris
Thanks for using GetSimple! - Download

Please do not email me directly for help regarding GetSimple. Please post all your questions/problems in the forum!
Reply
#11
ccagle8 Wrote:
  • Allow developers to create their own folder within their plugin structure like this: '/myplugin-folder/lang/'
  • Give them a function that allows them to "merge" their language file (which is an array just like before) with the site-wide language file. Something like this: i18n_merge('../path-to-my-plugin/lang/en_US.php');

Nice compromise, but I would change the function signature to i18n_merge('myplugin-folder', 'mylanguage') where 'mylanguage' is optional and set to $LANG if not given.
  • that way the plugin's directory structure regarding translations is enforced,
  • the keys must be automatically prefixed with 'myplugin-foler/' by the i18n_merge function, otherwise plugins will overwrite each other's texts
  • texts should be merged (although with a prefix that's not really important), i.e. if the key already exists, it is not overwritten
  • i18n_merge returns true if the language file exists, false otherwise.

Normally the admin language and the frontend language are the same and using english as default is reasonable, thus the standard code in plugins would be:

Code:
if (!i18n_merge('myplugin')) i18n_merge('myplugin', 'en_US'); // or another default language
...
i18n('PAGES'); // accessing standard GetSimple text
i18n('myplugin/MYTEXT'); // accessing plugin specific text

I don't think renaming the file to language.php is a good idea - it means one more manual step on installation for the user, even if his language is supported by the plugin. And with the I18N plugin or a future GetSimple supporting one language per user it would not even work.

It's as easy for the user to copy a file to say "it-IT.php" and translate it. And when he is happy with it, he should be encouraged to send it to the plugin developer.
I18N, I18N Search, I18N Gallery, I18N Special Pages - essential plugins for multi-language sites.
Reply
#12
mvlcek Wrote:It's as easy for the user to copy a file to say "it-IT.php" and translate it. And when he is happy with it, he should be encouraged to send it to the plugin developer.

Agreed. It will be up to the translator and plugin developer to coordinate packing translation files.

mvlcek Wrote:I don't think renaming the file to language.php is a good idea

Agreed, but maybe certain plugin developers don't have the time or know-how to create a language switcher within their plugin. This is a decent alternative.

mvlcek Wrote:texts should be merged (although with a prefix that's not really important), i.e. if the key already exists, it is not overwritten
I would have to look into how PHP handles array merges. Hopefully the prefixing is possible.

I like the idea of forcing the directory structure with the i18n_merge('myplugin-folder', 'mylanguage') call. It will allow anyone using a plugin to know exactly where the language files are to be placed.

mvlcek Wrote:Nice compromise
Thanks!
- Chris
Thanks for using GetSimple! - Download

Please do not email me directly for help regarding GetSimple. Please post all your questions/problems in the forum!
Reply
#13
I will update the function accordingly and post it/send it to you.
I18N, I18N Search, I18N Gallery, I18N Special Pages - essential plugins for multi-language sites.
Reply
#14
The function(s) would be:

Code:
function i18n_merge($plugin, $language=null) {
    global $i18n, $LANG;
    return i18n_merge_impl($plugin, $language ? $language : $LANG, $i18n);
  }

  function i18n_merge_impl($plugin, $lang, &$globali18n) {
    $i18n = array();
    if (!file_exists(GSPLUGINPATH.$plugin.'/lang/'.$lang.'.php')) return false;
    @include(GSPLUGINPATH.$plugin.'/lang/'.$lang.'.php');
    if (count($i18n) > 0) foreach ($i18n as $code => $text) {
      if (!array_key_exists($plugin.'/'.$code, $globali18n)) $globali18n[$plugin.'/'.$code] = $text;
    }
    return true;
  }

(the second function is a "private" function needed because the plugin's language file also sets $i18n).

BTW: it would be nice to have a function to determine if the plugin is included for the frontend or the admin backend, like:

Code:
function is_admin() {
  return basename($_SERVER['PHP_SELF']) != 'index.php';
}


Not sure, if this is the best way.
I18N, I18N Search, I18N Gallery, I18N Special Pages - essential plugins for multi-language sites.
Reply
#15
Thanks mvlcek. Did you try any of this out? I would add these to the template_functions.php file and see what happens if you didnt yet.
- Chris
Thanks for using GetSimple! - Download

Please do not email me directly for help regarding GetSimple. Please post all your questions/problems in the forum!
Reply
#16
ccagle8 Wrote:Thanks mvlcek. Did you try any of this out? I would add these to the template_functions.php file and see what happens if you didnt yet.

I tried them out and they seem to work.
Make sure to put them into a file where they are available in the admin backend and in the frontend - functionally they probably belong into the same file as i18n() and i18n_r(), basic.php?
I18N, I18N Search, I18N Gallery, I18N Special Pages - essential plugins for multi-language sites.
Reply
#17
are i18n() and i18n_r() available to the front end? Yeah, looks like they would have to be in basic.php would have to be the place if they need to be accessible to the front end too.
- Chris
Thanks for using GetSimple! - Download

Please do not email me directly for help regarding GetSimple. Please post all your questions/problems in the forum!
Reply
#18
ccagle8 Wrote:are i18n() and i18n_r() available to the front end? Yeah, looks like they would have to be in basic.php would have to be the place if they need to be accessible to the front end too.

Include structure seems to be:
Code:
index.php
- gsconfig.php
- admin/inc/common.php
    - admin/inc/nonce.php
    - admin/inc/xss.php
    - admin/inc/basic.php
    - admin/inc/template_functions.php

So both files should work. Not sure why template_functions is always included.
I18N, I18N Search, I18N Gallery, I18N Special Pages - essential plugins for multi-language sites.
Reply
#19
i went ahead and added it to basic.php in SVN. Thanks
- Chris
Thanks for using GetSimple! - Download

Please do not email me directly for help regarding GetSimple. Please post all your questions/problems in the forum!
Reply
#20
By the way: I saw your Wiki article for this: very well done!
- Chris
Thanks for using GetSimple! - Download

Please do not email me directly for help regarding GetSimple. Please post all your questions/problems in the forum!
Reply
#21
The Translate plugin allows the easy creation and translation of language files, for GetSimple itself and for plugins conforming to the new guidelines for internationalization.

The sales pitch can be found here.
I18N, I18N Search, I18N Gallery, I18N Special Pages - essential plugins for multi-language sites.
Reply
#22
@mvlcek: haha - you've taken over the GS plugin world with all your plugins. great work, and i'm proud that our plugin system has become so powerful... all it takes is someone with a mind like yours to take it places i never thought it could.
- Chris
Thanks for using GetSimple! - Download

Please do not email me directly for help regarding GetSimple. Please post all your questions/problems in the forum!
Reply
#23
I've updated the wiki.

One correction was the key => value was specified as key = value

Added a bit on using i18n_r() when a return is needed rather than an echo.

Thanks for the docs! Got my plugin converted easily once I figured out these two things!

-Rob A>
Reply




Users browsing this thread: 2 Guest(s)