I have had some discussions with module maintainers about context sensitive translations with links. They often do not add "a href" inside their translatable strings and add an additional string with the link text. This should be avoided to allow context sensitive translation. I have had many troubles with this in "update_status", "project" and some other translations.

I think we should write-up why it is better to add "a href" to a translatable string however this will add some HTML and not to split this into two strings. This should be added to the upgrade handbook for D6.

A bad example what i'm talking about:

'#description' => t('The default priority for specific content types can be set on the !link pages.', array('!link' => l(t('content type settings'), 'admin/content/types'),)),

And here how i think - this should looks like to be much easier to translate without side effects:

'#description' => t('The default priority for specific content types can be set on the <a href="!link">content type settings</a> pages.', array('!link' => url('admin/content/types'))),

Comments

Gábor Hojtsy’s picture

Project: Drupal core » Documentation
Version: 6.x-dev »
Component: documentation » Developer Guide

Why document this in the upgrade handbook? I'd like to get a "How to write Drupal translatable interfaces" guide done for module and theme authors, and actually kicked this off with a cheat sheet as a quick takeaway. Maybe you can help with tips on revising the cheat sheet. I also hope to make better documentation for module and theme writers on drupal.org and/or published in some more compact form. The cheat sheet idea itself came to let the guys understand that this is not hard, there are simple rules to follow.

Moving to the developer guide.

hass’s picture

Title: Translateable strings should be context sensitive » How to write Drupal translatable interfaces

How to write Drupal translatable interfaces

Well, that's a much better title and will not only focus on the special problem that drives me crazy to discuss the 100th time :-). Changing title for now... i could review this partly, but i'm sure i don't know all of the requirements such good as you do...

Maybe this could be a good GHOP job, isn't it?

Gábor Hojtsy’s picture

Indeed, it could be. Care to submit the idea on groups.drupal.org? (Handbook pages on drupal.org would be the deliverables).

webchick’s picture

I've love to make this a GHOP task, but we need more details on what exactly such a document would need to cover. Please see the guidelines at http://code.google.com/p/google-highly-open-participation-drupal/wiki/Ho...

hass’s picture

@webchick: I would try to explain... hope you get an idea how to shorten this into a GHOP task. Maybe Gabor could give some more on this.

We need someone explaining how to make a Drupal Modules or Themes translatable in general. So we should explain there is a t() function. The function is also available in JS from D6+. All existing handbooks (http://drupal.org/translators) should be reviewed. I'm not sure what is already written or not, but i cannot find something. The writeup should provide examples how code must looks like and what is not good.

Bad:
t('I don\'t like foo.')
t("I don't like". $foo)

Good:
t("I don't like foo.")

Other things are:
1. Do not include variables into t() like t($example) if there this string is dynamically or configurable.
2. Explain some more bad style examples (and what POTX don't like and what's wrong).
3. Explain why strings should not use other string variables (see intro here), context sensitive translations and explain the possible problems
4. t() should whenever possible - do not contain HTML (except content sensitive translations with links)
5. Do not add line breaks inside t().
6. Do not split t() strings over multiple lines separated with DOT's. Example:

t('adsasd adasdasda asdadssa'.
  'asad asad adssdada')

I could give some feedback on this, but i'd like to please "Mr International" (Gabor) to review this, while i'm not sure if i know all...

zirvap’s picture

A couple of useful links:

http://hojtsy.hu/blog/2007-nov-15/make-jump-ensure-your-drupal-modules-a...

http://api.drupal.org/api/function/t/6 and http://api.drupal.org/api/function/t/5

When this handbook page has been written, there should be links to it from the handbook pages http://drupal.org/node/296338 (which currently links to this issue) and http://drupal.org/node/254214.

nielsbom’s picture

Component: Developer Guide » New documentation

Changed the component to reflect the new component categorization. See http://drupal.org/node/301443
-nielsbom

Gábor Hojtsy’s picture

http://drupal.org/node/312523 is the coder module integration issue for potx module which would benefit greatly from this page to point to with potx error messages.

stella’s picture

Yes, even ignoring coder's need for it, I think such a documentation would hugely benefit the developers. For the most part, I think developers just don't know that they shouldn't be passing variables, etc, to t(). However, as well as documenting what shouldn't be done, it should also document best practises. I'm specifically thinking of translating dynamic variables here.

hass’s picture

An often ignored documentation can be found at http://api.drupal.org/api/function/t

An also often ignored and possibly unwritten and rule is that developers don't finish their sentences with periods...

Gábor Hojtsy’s picture

Assigned: Unassigned » Gábor Hojtsy

Going to make some time for this next week. Expect a big page or pages coming out of my keyboard then.

zirvap’s picture

I just found this handbook page: Module developer's guide > Multilingual support, which covers some of this topic.

Gábor Hojtsy’s picture

zirvap: It is a far cry, from what should be documented unfortunately. (Yes, I am working on this but the comprehensiveness I am trying to achieve does not let me go forward fast enough.

Gábor Hojtsy’s picture

Ok, instead of sitting on what we have any longer, I've started to add the three pages I wrote to the handbook: http://drupal.org/book/export/html/322729

This forms a new "Localization API" section in the Drupal APIs section of the documentation. The page linked by zirvap is basically about translating user input, not making it possible to translate the interface of a module which is the issue at hand. Feedback is welcome. I have lots of more pages in the pipeline to be written. Next up is a page titled "Dynamic or static links and HTML in translatable strings". Lots of fun there.

Gábor Hojtsy’s picture

Huh, I think the guide is almost complete :) It has the following subpages:

  • Two backends for translations: installer and runtime
  • Dynamic strings with placeholders
  • Dynamic or static links and HTML in translatable strings
  • Formatting numbers, dates/times, sizes and intervals with localization
  • Strings at well known places: built-in menus, permissions, log messages and .info files
  • Translating strings in JavaScript

I've worked on this quite some this last week and over this weekend. I've also double checked, validated and included my cheat sheet on the intro page, since it is IMHO the best quick summary of all the little things involved. I say this is almost complete, as I see at least one thing missing: translating emails. That is a bit special, since it requires handling the target user language. Otherwise I think this is a pretty decent guide now as it is, and will serve great to link to from potx coder error messages as well as hass pointing all kinds of developers to these pages while submitting bugs :)

Feedback is welcome!

Gábor Hojtsy’s picture

Ha, yeah, of course I'd also like to include a "teaser page" on translating user input, which would basically explain that t() should not be used for that in general, and Drupal 6 provides such an API but i18nstrings is the module which implements it. Just to set things straight as people would ask this anyhow a lot of times :)

hass’s picture

Nice. I would like to take a deeper look to the text... only checked the code examples now and overflown a very small part of your texts at http://drupal.org/node/322729.

I'd like to ask a few things:

1. I thought we should use t() in hook_schema()... but I read $t(). Core is also using t() in schema definitions - I assume your example needs some work!? I'm not sure when I need the schema strings at install time as it is only used by schema API as I know... never seen this strings somewhere else.

2. I also thought placeholders should use underscores like PHP variables... for e.g. @drupal-handbook should become @drupal_handbook. I'm not sure if we should make a recommendation or a rule for using underscores here. I have changed some module strings from minus to underscore... maybe a useless change.

3. I would also know what you think about EM's in strings foo <em>bar</em> foo.. dww asked me some time ago why I'm using them as they are the default theme placeholders and if we hardcode them in the strings we are no more able to change them by changing the theme placeholder globally... I wasn't sure what to answer on this and I'm confused myself, too :-).

Gábor Hojtsy’s picture

1. My thinking was that basically hook_schema() is run in install time to create the database tables. t() uses the database, and therefore t() should not be used in functions which fiddle with the database (such as update functions and the schema hook). Well, actually, the schema hook itself does not do anything, but you probably get the idea that it is used to build up the database.

Interestingly, system.install uses t() in its schema hook. Well, since when it is installed, locale module will surely not be installed, it should not be a problem. Also locale.install uses t(). I think it works because when the schema hook is invoked, the module is not yet installed, so the database is not looked at. After that, the database can be looked at for t() stuff. Well, we can reverse on this and suggest using t() in schema hooks, it does indeed work.

2. Well, Drupal's locale module uses @content-help, @add-language and friends. Token module, one of the most common base modules reused by a miriad of other modules also uses %site-name, %user-mail and so on. I wrote into the docs, that Drupal core itself is inconsistent in this, but the hyphen is generally suggested to be used, not the underscore. The hyphen is way easier for translators to actually notice in the text and not translate the continuation of the placeholder as if there were words there. Compare %site-name to %site_name.

3. If you'd use it like <em>@value</em> then it is indeed a bad idea. If you just emphasize some part of the string which is not a placeholder, such as Users think this is a <em>good thing</em>., then I say use it. I wrote the text to suggest using inline markup but avoid using block markup. It should possibly be expanded to also say complex inline markup is discouraged (such as styles, onlick and whatever other nastiness :)

Gábor Hojtsy’s picture

My original writing included suggestions for format_plural() usage to use @count in the singular parameter as well. Since that make no sense given that translations in need of @count there could just include count, and even the Arabic example I've provided does not use @count in all cases, I've gone back to suggesting the simpler English form: http://drupal.org/node/323072/revisions/view/374597/374817

Gábor Hojtsy’s picture

Made the same change for the JS translation page: http://drupal.org/node/323109/revisions/view/374642/374819

Gábor Hojtsy’s picture

Following on the above suggestion from hass, I've updated the docs to say that the schame hook should use t() instead of $t(). Also, documented that update functions just should not use this API. http://drupal.org/node/322731/revisions/view/374097/375095

hass’s picture

@Gabor: Could you take a look on http://drupal.org/node/290150#comment-947813 and do some brainstorming on dww's questions, please. :-)

hass’s picture

What about using $t() in update functions? t() sounds like making no sense as the translated strings will be imported afterwards installation and PO files are also not (re-)imported on upgrades to import missing strings from new versions... so $t() should be the right direction... but should we really do a get_t() in all update functions that have a translatable string?

Using $t() in update functions would allow us to translate the complete install process, isn't it? This also seems to be missing in D6 Core. See system_update_6026 in system.install.

Gábor Hojtsy’s picture

From where would $t() get translatable strings in the update process?

hass’s picture

I thought this strings will be loaded into memory from the various small install.de.po files of modules. D6 POTX creates this files for us...

Gábor Hojtsy’s picture

st() was designed to be used in the installer and is therefore loading in ONE .po file from the /profiles directory macthing for the current profile and language when installing Drupal. It does not load anything from the modules themselves.

hass’s picture

Are we able to also load the modules install PO files? Why do we have this files if not for the install process if they are unused? Was this planned for D7?

add1sun’s picture

Hrm, is this issue still pending or is it pretty much done and further changes can be made as needed?

arianek’s picture

Status: Active » Fixed

@add1sun this seems to be pretty much resolved to me - the handbook pages have been updated, and as mentioned, one .po loads with the install (and others can be downloaded later if needs be) so the documentation stands for that.

marking as fixed (please open new issues for any smaller fixes)

Status: Fixed » Closed (fixed)

Automatically closed -- issue fixed for 2 weeks with no activity.