Webrocker Posted July 18, 2015 Share Posted July 18, 2015 Hi, I'm toying with the idea of having a central place in PW's translation system for phrases and strings that are frequently used throughout several template files. The way I understand PWs translation system after reading the docs (http://processwire.com/api/multi-language-support/code-i18n/) is that everytime a __('translate-me') is used in a different .php file, the system will pull that 'translate-me' in a context of the .php file where it is used - so basically all translatable strings of _one_ file at a time are manageable via the (very cool) translation tool in PW's admin interface. So if for example I were to use __('Daytime phone number') in, lets say, the home.php as well as in the login.php and maybe a profile.php, I'd need to translate this three times, right? - A solution given in the docs is using the gettext context, and have this pointing to the first template file where the string was used first, so I only need to translate that template's strings and the other two will "see" their translation threre. So in my fabricated example: //home.php: __('Daytime phone number'); //login.php: __('Daytime phone number','/site/templates/home.php'); //profile.php: __('Daytime phone number','/site/templates/home.php'); So I only need to look for the translations of /site/templates/home.php in the translation tool and the other occurances of that string will be taken care for. This now brings me to the idea of creating a php file in, say, "/site/language/strings.php". So what I can now do (but what feels kind of hacky to me…?), I use all the frequently used strings of my several template files in this "strings.php" file, wrapped in their language functions like __('translate me'). in _init.php or maybe in config.php I store this file's path for the context: $i18lctx = '/site/templates/language/strings.php'; And now I can use the transalatable strings in several template/php files like this // in home.php, in archive.php etc __('Hello pilgrim',$i18lctx); In PWs admin interface I'll have all the strings in one place: the strings.php (?textdomain=site--templates--language--strings-php). Is this the right way to go about it or am I overlooking a basic fact (maybe like, dude, this is what the language packs are for)? Cheers, Tom 4 Link to comment Share on other sites More sharing options...
tpr Posted July 18, 2015 Share Posted July 18, 2015 I think it's just fine using strings.php if it helps you - actually I'm using this right now, the only difference is that I named it "_strings.php", to avoid showing up as a template file. Another simple solution can be found here, making a dedicated page for strings: https://processwire.com/talk/topic/10443-how-to-do-this-global-vars/ 1 Link to comment Share on other sites More sharing options...
ryan Posted July 18, 2015 Share Posted July 18, 2015 I use a similar solution to a _strings.php file, and include it from my _init.php file (prependTemplateFile), so that it's available to all templates. But I bundle all the translated values into a new function (which I'll call _t(), but you could name it whatever you want). So you can call upon that _t() function anywhere that you'd call a __() function. For instance, in your /site/templates/_strings.php file... function _t($label) { static $labels = null; if($labels === null) $labels = array( 'Yes' => __('Yes'), 'No' => __('No'), 'Maybe' => __('Maybe'), 'And so on...' => __('And so on...') ); return isset($labels[$label]) ? $labels[$label] : $label; } From there, you can replace any __('label') call with _t('label'). In this manner, you only need to translate your _strings.php file, and all the other template files can use the translated labels. For the cases where you need to translate text that only exists in a particular file, then you'd continue to use the __() function as usual. 7 Link to comment Share on other sites More sharing options...
tpr Posted July 18, 2015 Share Posted July 18, 2015 I'm using almost the same setup, but my "t" function handles context too. The good thing is that _strings.php can be copied to your next projects too. function t($text, $context = 'General', $textdomain = '/site/templates/_strings.php') { return _x($text, $context, $textdomain); } _strings.php: // Search _x('Search site', 'Search'); _x('No matches', 'Search'); // Forms _x('From', 'Forms'); _x('From email', 'Forms'); _x('To', 'Forms'); ... 12 Link to comment Share on other sites More sharing options...
Webrocker Posted July 18, 2015 Author Share Posted July 18, 2015 hi, thanks for the answers, I think i'll adapt this 't' function concept to my project. this removes the 'hacky' feel of my approach with it's duplicate level of __('foo') functions, in _string.php and the template files. cheers tom Link to comment Share on other sites More sharing options...
ryan Posted July 19, 2015 Share Posted July 19, 2015 tpr's solution is better than the one I posted. To take it a step further, those _x() functions never even need to execute. They can simply be contained in a PHP comment, as they only need to be visible to the language parser, which parses the files directly and doesn't execute the with PHP. So you could do this: /******************************************* Intentionally commented out // Search_x('Search site', 'Search'); _x('No matches', 'Search'); // Forms _x('From', 'Forms'); _x('From email', 'Forms'); _x('To', 'Forms'); ... *******************************************/ Of course the actual t() function should not be commented out though. 5 Link to comment Share on other sites More sharing options...
tpr Posted July 19, 2015 Share Posted July 19, 2015 To take it a step further, those _x() functions never even need to execute. They can simply be contained in a PHP comment Indeed! Thanks for this extra step! 2 Link to comment Share on other sites More sharing options...
tpr Posted July 21, 2015 Share Posted July 21, 2015 And one more: function n($singular, $plural, $count) { echo t(_n($singular, $plural, $count)); } This handles translations of singular/plural nouns, using the earlier introduced "t" helper. Of course strings have to be listed in "_strings.php" to be translatable in the admin. (I had to use "echo" instead of "return", probably because the template engine I'm using) Usage: n('minute', 'minutes', $page->count_of_something) Using "/*!" instead of "/**" will prevent addition of stars when hitting new lines in IDEs: /*! Intentionally commented out GENERAL _x('minute', 'General'); _x('minutes', 'General'); SEARCH _x('Search site', 'Search'); _x('No matches', 'Search'); *******************************************/ 1 2 Link to comment Share on other sites More sharing options...
Fudins Posted July 22, 2015 Share Posted July 22, 2015 Hello, I have the following structure in my project: _head(which includes _head) _header _foot I made a translation like echo "".__("Live long and prosper!","/site/templates/_header.php").""; but my website gives a "ERR_EMPTY_RESPONSE". I premuse that the problem is on the translation ou using translation in this template. Anyone have a clue what it might be? Best Regards Link to comment Share on other sites More sharing options...
tpr Posted July 22, 2015 Share Posted July 22, 2015 This error is rather caused by the server and not your code (at least that's what I found on Google). Does the error go away if you remove that line? Btw you could echo the translation in a simpler way: echo __("Live long and prosper!", "/site/templates/_header.php"); Link to comment Share on other sites More sharing options...
Fudins Posted July 23, 2015 Share Posted July 23, 2015 Hello, Yes, if i remove the line the error goes away. And if i ignore _header template and make the translations only at _head template, there is no error anymore. It is beacause i am using a diferent template, from _head and _foot with "_" ? regards. Link to comment Share on other sites More sharing options...
Stikki Posted August 21, 2015 Share Posted August 21, 2015 My solution was following: function t($text) { return include(wire('config')->paths->templates . '_translations.php'); } _translations.php: <?php $translations = []; $translations[$text] = _x('String', 'General'); return $translations[$text]; This to avoid actual function file to be translatable at any point + better access for strings overall. EDIT: Actually, this was good idea, but ain't working Sorry about posting, back to drawing board. Link to comment Share on other sites More sharing options...
felic Posted August 31, 2015 Share Posted August 31, 2015 Hi, seems i am missing something. The strings to translate (from file _string.php) shows up in the admin language template and are being translated. But no change appears (or even getting errors) if i switch the language in the frontend. The pages are simply outputs whats being plain written in the template file, e.g the default language string. Maybe one of yours is so kind to confirm the following steps i did so far or - even better - give a hit where i go wrong, e.g. what i forgot to consider . I got a _init.php file which is prepended before any other file (config.php). This init file includes the related files: // Shared functions include_once("./_func.php"); // Translation strings include_once("./_strings.php"); _func.php contains the function function _t($text, $context = 'Generic', $textdomain = '/site/templates/_strings.php') { return _x($text, $context, $textdomain); } while _strings.php contains the translation files /*! _x('Soziale Netzwerke', 'Footer'); _x('Sprachwahl', 'Footer'); */ Within template home.php for example those strings are printed like this: <?php echo _t('Soziale Netzwerke');?> Any hint what i am missing here is much appreciated! Thanks a lot in advance, regards Link to comment Share on other sites More sharing options...
tpr Posted August 31, 2015 Share Posted August 31, 2015 I guess you simply forgot the context: <?php echo _t('Soziale Netzwerke', 'Footer');?> If you set no context, the default will be used ('Generic' in your example). So if you wouldn't like to write the context in your php files, you should add strings to the Generic context in your _strings.php: // _strings.php: _x('Soziale Netzwerke', 'Generic'); // then you can omit context in templates: <?php echo _t('Soziale Netzwerke');?> Read more on context here: https://processwire.com/api/multi-language-support/code-i18n/#context Link to comment Share on other sites More sharing options...
felic Posted August 31, 2015 Share Posted August 31, 2015 Hi tpr, I guess you simply forgot the context: <?php echo _t('Soziale Netzwerke', 'Footer');?> If you set no context, the default will be used ('Generic' in your example). So if you wouldn't like to write the context in your php files, you should add strings to the Generic context in your _strings.php: Thank you very much for your answer. I assumed to overlooked something. And here we go, the context was missing. All is doing fine now. Thx! Link to comment Share on other sites More sharing options...
adrianmak Posted May 12, 2016 Share Posted May 12, 2016 tpr method is really good for translation strings across templates. However, with using this method , in a situation of not just translated a one to two words label, but a medium long string with html tag Let's say an message to user In my current implementation, i have this translation code $registration_success_message = html_entity_decode(__("Thank you for registration. <br/><br/>Please wait for account approval from administrator.")); in the template , i will echo $registration_success_message; Link to comment Share on other sites More sharing options...
tpr Posted May 13, 2016 Share Posted May 13, 2016 You can use a page dedicated to translations. Just create multilanguage text or textarea fields and simply echo their content as usual. Link to comment Share on other sites More sharing options...
adrianmak Posted May 13, 2016 Share Posted May 13, 2016 support plain text string and string with html tag function _t($text, $context = 'general', $textdomain = '/site/templates/_strings.php') { return html_entity_decode(_x($text, $context, $textdomain)); } 3 Link to comment Share on other sites More sharing options...
tpr Posted May 13, 2016 Share Posted May 13, 2016 I see, thanks. I will think about it if it's a good practice, I use the same thing in my Latte module. Link to comment Share on other sites More sharing options...
tpr Posted June 17, 2016 Share Posted June 17, 2016 @adrianmak just needed the html_entity_decode in the current project so I'll add this to my module, thanks! Link to comment Share on other sites More sharing options...
bernhard Posted October 22, 2016 Share Posted October 22, 2016 just wanted to mention that the new version has support for common tags: https://processwire.com/blog/posts/processwire-3.0.38-core-updates/#added-support-for-common-multi-language-translations Link to comment Share on other sites More sharing options...
Orkun Posted February 10, 2017 Share Posted February 10, 2017 On 18.7.2015 at 3:33 PM, ryan said: I use a similar solution to a _strings.php file, and include it from my _init.php file (prependTemplateFile), so that it's available to all templates. But I bundle all the translated values into a new function (which I'll call _t(), but you could name it whatever you want). So you can call upon that _t() function anywhere that you'd call a __() function. For instance, in your /site/templates/_strings.php file... function _t($label) { static $labels = null; if($labels === null) $labels = array( 'Yes' => __('Yes'), 'No' => __('No'), 'Maybe' => __('Maybe'), 'And so on...' => __('And so on...') ); return isset($labels[$label]) ? $labels[$label] : $label; } From there, you can replace any __('label') call with _t('label'). In this manner, you only need to translate your _strings.php file, and all the other template files can use the translated labels. For the cases where you need to translate text that only exists in a particular file, then you'd continue to use the __() function as usual. Hi @ryan I have used this way to translate all of my strings and it works ("has worked") good. But now I have encountered something. A Client of mine called me and said that all the translations from the _string.php for the default languages were gone when he had added the translation for two other strings. The new changed Strings weren't gone but all other were it. Do you perhaps know what could cause such a dangerous action? The _strings.php file has 80-90 Translations at the moment. Greetings Orkun Link to comment Share on other sites More sharing options...
MilenKo Posted March 16, 2018 Share Posted March 16, 2018 Hello guys. I just found this topic while searching for a smarter way to translate the whole site using a single file instead of having repetitive translations in different templates. Tried to reproduce @tpr and @felic approach of using strings file but things got messed up. If I add: // Translation strings include_once("./_strings.php"); to my _init.php that is prepended in the config.php I am seeing the content of the file in my header As far as I remove the include from _init.php all the styles come back promptly. Trying to figure out what is wrong with the setup that worked for others, I decided to remove the include from _init.php again and add manually the strings.php file by going to the language administration and from there after clicking on Find Files To Translate I clicked on Enter file to translate at the bottom and added manually the path to my language file: /sites/templates/languages/strings.php After that I went back to the language translation and added my strings and voila, it all started working promptly. Now this raises a few questions for me: 1. What am I doing wrong to see the include in the header? 2. Do the include of strings.php in _init.php only allowing the file to be automatically found and listed in the translation files or there is another purpose? 3. Is is OK to leave the translation files out of the _init.php and add it manually during the profile work or there are some drawbacks I am not seeing yet? Link to comment Share on other sites More sharing options...
tpr Posted March 16, 2018 Share Posted March 16, 2018 Are you sure there's an opening php tag in the strings php file? I include that file in ready.php but I don't think that makes a difference. Link to comment Share on other sites More sharing options...
MilenKo Posted March 16, 2018 Share Posted March 16, 2018 Well I am sure that it is commented and tried to recreate the file several times. Here is the content of it: /* // Footer.php _x('CONTACT INFO', 'Generic'); _x('COMPANY LINKS', 'Generic'); _x('ABOUT US', 'Generic'); // About.php _x('OUR HISTORY & FACTS', 'Generic'); _x('LEADER IN THE REAL ESTATE MARKET SALES SINCE', 'Generic'); _x('GET A QOUTE', 'Generic'); */ That is what questioned me, why I see the comments in the header and that messes up the divs etc., however as soon as I remove the include it works if I manually add the file path for translation. I checked for some bizzaire code in the header but it is all good there so no explanation why would commented block appear... Link to comment Share on other sites More sharing options...
Recommended Posts
Create an account or sign in to comment
You need to be a member in order to leave a comment
Create an account
Sign up for a new account in our community. It's easy!
Register a new accountSign in
Already have an account? Sign in here.
Sign In Now