I know most sites will be with one "system language" even though the front end might have many languages, but in keeping with good Drupal customs, shouldn't the states and priorities be translatable elsewhere than in the database?

As far as I can see by quickly glancing at the code, packing the results in the internal functions _support_get_state() and _support_priorities() in the t()-function could do some of it, but as it seems that results are returned directly from the database in other functions like _support_priority_default(), these will probably need some work too.

Since the states and priorities are saved in the tickets as integers rather than text, it should be possible to make sure that all relevant texts are rendered through the t()-function making a multi-language translation possible and making it possible to export a complete translation and import or install it in another installation.

I have already hacked a copy of the module (hate doing that!) and it seems to work OK. If relevant I can point out the places that need recoding if anybody wants it. I have no experiences with producing proper patches, but I might dig out a tool to do it the proper way - again provided the interest is there.

Martin

Comments

jeremy’s picture

Category: feature » bug

Anywhere that these are not translatable is a bug, marking this issue appropriately. A patch would be most welcome.

Find information on how to create a patch here: http://drupal.org/patch/create

vertikal.dk’s picture

Jeremy,

Did my best to create a proper patch, and as far as I can see it looks OK. Hope it works.
These few edits enable standard translation of the states and the priorities. They are fairly crude and may need some beautification, but work.

Martin

vertikal.dk’s picture

Title: Translatabilty of states and priorities » Oops!
StatusFileSize
new1.46 KB

I can see that I added a couple of t()'s not needed. Here's an even smaller patch.

Martin

jeremy’s picture

Title: Oops! » Translatabilty of states and priorities
Status: Active » Needs review

Restoring title.

jeremy’s picture

Status: Needs review » Needs work

It seems that this is not the preferred method for providing this translation, from http://api.drupal.org/api/function/t:

However tempting it is, custom data from user input or other non-code sources should not be passed through t(). Doing so leads to the following problems and errors:

* The t() system doesn't support updates to existing strings. When user data is updated, the next time it's passed through t() a new record is created instead of an update. The database bloats over time and any existing translations are orphaned with each update.
* The t() system assumes any data it receives is in English. User data may be in another language, producing translation errors.
* The "Built-in interface" text group in the locale system is used to produce translations for storage in .po files. When non-code strings are passed through t(), they are added to this text group, which is rendered inaccurate since it is a mix of actual interface strings and various user input strings of uncertain origin.

What, then, is the correct way to handle this?

vertikal.dk’s picture

Jeremy,

Are the states and the priorities "user input"? I don't think so.

As far as I can see they get dug out directly from the database where support.install puts them when the module is installed.
Currently there seems to be no other customization or translation option than editing directly in the database tables, which is definitely not the proper way to do it in my opinion. That's a one language only solution, and hardly very kosher.

If the different states and priorities are stored in plain English in the database, why would it be wrong to pass them through t() when they get fetched, and through that obtain the right translation for the current user's language? The first time they are passed through they get registered as not translated and can be dug out and translated to any language.

There will be no orphaning or anything unless the states are changed in the database.

Martin

jeremy’s picture

Status: Needs work » Closed (won't fix)

The reason these values are stored in the database is so that they can easily be modified. Unfortunately the functionality has not yet been coded, but at an unknown future time it will be possible for admins to edit the status and priority values -- not only changing their names, but defining new ones altogether. Thus, yes, these values are "user input" by design.

I feel that these values should be translatable, but based on what I've read on the handbook page I linked this would be incorrect. It would only be correct if the states and priorities were hard coded arrays in the module, which they intentionally are not.

Customization of status fields are discussed in this issue:
#395814: Status & priorities customization

Feel free to re-open if you feel I'm misinterpreting the handbook page, or if you have a better solution.

vertikal.dk’s picture

Jeremy,

Sure the different states will be kind of user input if you make them configurable in the settings, but that won't solve the problem, namely translation. If you like me need a site, which caters to users with different languages you need "real" translation through Drupal's language handling system rather than a configurable semi-static set of texts in the database, which in the current system can be one language only and won't adhere to the user's selected UI-languange.

I'll stick to my hacks which work perfectly for multilingual sites and will do so even after you change or add states and priorities to the database - manually or through a settings page. I still find that this is not "true user input".

No matter what you decide, your work on this module is highly appreciated. Thanks!

Martin

jeremy’s picture

Yes, that all makes sense.

However, according to this page, "instead, translation of these data can be done through the locale system, either directly or through helper functions provided by contributed modules." So it's saying to not wrap this text in t(), and instead to rely on the locale system. Does this work for you? Or what am I missing?

vertikal.dk’s picture

Jeremy,

Well, it might be me who's missing something, but I think t() and the locale system are very tightly intertwined. t() calls a function called locale() if the locale module is enabled.

Most of the sites that I build run in Danish some even in several languages, and I always need to use the locale module and translate a lot of strings. I have most of the support module under control and translated into Danish using locale and the standard Drupal translation functions. As a Drupal coder from a very small language area this is pure routine. Whenever I bump into some English string, I simply search for the string (/admin/build/translate/search), write my translation, and viola!

My own modules also use t() for all strings. They get coded in English and translated through locale.

But I could not find the strings for the states and the priorities of the support module using the language/locale system. Since they never pass through t(), they never get written to the locales_source table, and won't be available for translation through the locale system as far as I can see.

I can't see how these can be translated in any other way, but it might just be me who is ignorant on the deeper lying mechanics of Drupal.

I'm at loss how this translation could be done differently - especially on multi language sites, which rely heavily on the t() function and locale.

The Drupal docs mention hook_locale functions as an option to cope with non-literal strings - such as variable based strings read from a database or generated dynamically. It does however not go into details about how to do so.

On the other hand there is a mention of a dummy function, which can obviously poke strings into the database in a proper way.

"strings that are loaded into variables in Drupal for output. In these cases, module authors may include a dummy file that passes the relevant strings through t()"

I can't see exactly where such a dummy function should go in the module, but it obviously just needs to be called once (like when the settings are saved), and after that you can call t() with the variable names and not the literal strings.

So as far as I can see, if you added something like

$void=array(t('new'), t('active'), t('pending'), t('closed'), ... );

in support_admin_settings(), the t() construction in support.module would be allowable... maybe?

Martin

jeremy’s picture

Status: Closed (won't fix) » Needs work

I'm hoping someone else more involved with the translation system can weigh in on this. I'd like to fix this properly, and at this point I'm unsure what the proper way actually is.

nancydru’s picture

gábor hojtsy’s picture

t() is not supposed to be used to translate user input. However, the i18n module suite, which those needing to translate sites use anyway (since otherwise you cannot translate blocks, menus, taxonomies, etc) provides an api function called tt(). Drupal core supports multiple "textgroups" in the locale system, but t() always uses the default ("code defined text" group). The tt() function however exploits this underlying support to store the string in a textgroup you specify. People will therefore see on the UI (which is either the core UI or i18n's UI) that strings are available to translate in your textgroup.

This would probably be best documented in the handbooks with the locale API.

jeremy’s picture

I'm still unclear as to what is the proper solution. I can either add a t() around the default database values (which the t() page seems to say is incorrect), or I can build a dependency on a third party translation tool and then add a tt() around the default database values? Neither really seems desirable to me, though I'd be more apt to do the former even if technically wrong rather than doing the latter, as most people that use this module will not need multilingual translations.

jeremy’s picture

There is currently a discussion on the Drupal development mailing list about this, starting here:
http://lists.drupal.org/pipermail/development/2009-September/033796.html

pasqualle’s picture

http://drupal.org/node/304002
read section: Working with the Internationalization - String Translation module

You do not have to add i18nstrings module dependency. But if the i18nstrings module is not enabled, then the statuses won't be translated. I think that's the correct functionality..

arhak’s picture

this issue should be aware of #395814: Status & priorities customization

atodorov’s picture

Hi all,
I've read all the comments on this issue, the discussion on the mailing list and the provided links which propose different ways to solve the issue. I've also read the #395814: Status & priorities customization issue. Looks like translation and customization are not that easy. Here are some thoughts and ideas as I try to understand the issue better:

1) I agree with Jeremy about comment #5. Passing variables directly to t() is BAD because the source text in English cannot be extracted into the POT file and hence can't be translated by module translators into PO files.

2) This issue and also #395814: Status & priorities customization should take into account the workflow process - The NEW issues becomes ACTIVE when first update is made. This is automatic transition as far as I can see from how the module works. What if one decides to delete ACTIVE from the DB and not use it at all?

3) The support_ticket tables stores state and priority fields as indexes not text which is good. Why do we have the support_states and support_priority tables? Looks to me that they are only for display purposes and probably to define some part of the workflow.

Here's an idea:
Step one is to make those strings translatable. Make a set of pre-defined statuses/priorities (together with "undefined" probably), something like:
STATE_NEW = array(0, t('new'))
STATE_ACTIVE = array(0, t('active')), etc.

Make those arrays or constants as you prefer. Wrap the text in the t() function. Indeed you already have code similar to this such as $states = array('all', 'my open') + _support_states() but not wrapped in t().

Make use of the numeric index or the constant name in all workflow logic/if statements instead of the text. You are probably already doing this, I haven't looked in details. I guess priority is only for display purposes but you can apply this principle to that as well.

This will enable site admins to translate the text while keeping the module logic unchanged. In reality users can't change those values, they can only select from a predefined set of them.

After this step is complete we can drop the support_states, support_priority tables because they will become obsolete.

Step two is to enable additional statuses and priorities. This is usually done at install time or very rarely when the site support procedures are updated. This is also performed by admins so UI or config file is not much of an issue as well. What I propose for this step is to make the pre-defined statuses and priorities immutable. If the admin wants additional ones just provide them with a mechanism to add them but don't let them modify or delete. It's probably wise to have a status/priority enabled/disabled checkbox for the pre-defined values so that they don't appear in the UI.

The mechanism to include additional statuses/priorities can be a php file, say support.mystatuses.php with a predefined format. The format can be a simple array with a well known structure to define the statuses and probably a workflow (I don't know if that's needed). Same thing for priorities. The support module will try to load this file if it exists and append the values to its internal data structures (the arrays from step 1, or a copy of them) so things like:
foreach ($statuses) continue to work without a change.

Site admins can easily make this file if they have an example and add the desired strings in their native language or wrap them in t() if they wish.

Any feedback and ideas are very welcome.

@Jeremy,
I'm willing to work on a patch for this and help you because I need it for my site. First thing I can do very quickly is to wrap with t() the places where strings like "all", "all open", "my open" are used. This will solve a minor issue for my particular site where the tickets tabs at user pages are in English (I don't allow selection of statuses and priorities for now).

Also let me know what do you think and in what steps this can be solved in your opinion.

Regards,
Alexander.

jeremy’s picture

Hi Alexander,

Thanks for taking a look at this. I have mixed emotions about your planned solution, as the whole purpose of storing these fields in the database was to make it easy to define your own status fields. That said, it clearly never quite worked out that way as it was a feature I never personally needed.

Moving the state fields into a PHP file moves me away from my next major goal with this module, which is to turn support clients and tickets into CCK node types allowing the arbitrary definition of your own states and other custom fields. That said, I may only implement this in the Drupal 7 branch of the module, where Fields is part of core.

> 1) I agree with Jeremy about comment #5. Passing variables directly to t() is BAD
> because the source text in English cannot be extracted into the POT file and hence
> can't be translated by module translators into PO files.

Correct & agreed.

> 2) This issue and also #395814: Status & priorities customization should take into
> account the workflow process - The NEW issues becomes ACTIVE when first update
> is made. This is automatic transition as far as I can see from how the module works.
> What if one decides to delete ACTIVE from the DB and not use it at all?

That's untested, but the actual workflow is defined by the phase1, phase2 and weight fields. If you deleted the active row, I assume that tickets would be auto-assigned to the 'pending' state. It's possible this is hard coded somewhere, but that would be a bug as it's not supposed to be.

> 3) The support_ticket tables stores state and priority fields as indexes not text which
> is good. Why do we have the support_states and support_priority tables? Looks to me
> that they are only for display purposes and probably to define some part of the workflow.

Correct, it's for display and workflow purposes -- and the ID that's stored in the tickets comes from the "sid" in the support_states table. Yes, this could all be moved into a text file, but then the only way you'd be able to configure this yourself would be to edit PHP code. That's not a usability improvement imo.

arhak’s picture

@#18
using t within a define doesn't seems to be a good idea (IMO)
take for example the huge problem upgrading from D 6.15 to 6.16 with the new locking framework
modules having t on define are getting trouble (as far as I recall)
other way could be having the constants defined in English and use t on those constants

but the solution I would recommend would be having conditional code to take advantage of i18n module, which addresses this limitation of t providing a tt function (check its submodules to know how to take advantage of tt)
there are also contrib modules which conditionally use tt when i18n is detected (right now I don't recall which modules)

EDIT: broken link

atodorov’s picture

Hi Jeremy,
thanks for your answer. It looks like nothing can be done for the 6.x series of this module, or at least nothing that you're happy with.

I've read quickly the fields API/CCK module description and that looks really exciting new feature. Given your previous comment I think it will be best for all if you can share more about your plans for the future of this module in Drupal 6 and 7, i.e. are you going to do bugfix and maintenance releases for Drupal 6 or only concentrate on Drupal 7, what new features you're planning to include, etc. If we can't or don't want to fix this in 6.x then let's discuss the future version.

lameei’s picture

+1

gorgo’s picture

Hi,
I really need to translate these strings as well.
Could somebody please explain in more detail how this can be done with i18n?

Ivan Simonov’s picture

I consider untranslatable states and priorities is a bug.
Interface of my site is translated. I want to use this module.
But I can not explain my users what is "new/low/hi/pending". They want to use native language.
English fields on non-english site looks terrible.

As I see default states and priorities can not be changed via web-interface.
So it is no problem to use t() function for other languages.
If you provide ability to translate it, you give freedom to customize states and priorities for non-english speakers at least. It is a big community.

If you want to use t() function you can put array with custom states to "settings" table.
And add /admin/support/states page with interface for set any names for states and priorities.
(Possible it will be table: states_name\language for multilingual support)

May be it is temporary steps, but it will be useful in D6 branch.
Thanks.

Ivan Simonov’s picture

It is funny! I wrote long letter and then go to phpMyAdmin.
I just change states and priorities in the corresponding tables.
I use my native language. Seems it works for me.

Another way is to add page where administrator can redefine or translate values stored in support_priority and support_states tables.

Good luck.

Exploratus’s picture

I can confirm I just changed them in phpmyadmin and it worked fine..

sinasalek’s picture

Version: 6.x-1.1 » 7.x-1.x-dev
Status: Needs work » Active

One good example is perhaps entities and taxonomies, if support used taxonomies or a separate entity for state and priority they could have easily be translated.
So the easiest solution perhaps can be turning them into entities

sinasalek’s picture

The problem we're facing here is the same as Core's Contact module and as you may now i18n module comes with i18n_contact module that make the contact module categories translatable!
So the solution is already out there :)

sinasalek’s picture

Status: Active » Needs review
StatusFileSize
new2 KB

And finally a solution :)
This patch adds a new support text group "Support" , and both states and priority can be translated easily using admin/config/regional/translate/i18n_string.
Lets get it over with after over 3 years!

-alex-’s picture

#29 This doesn't work for me.
This destination "admin/config/regional/translate/i18n_string" doesn't exist.

sinasalek’s picture

You must install i18n string module (sub module of i18n module)

-alex-’s picture

This works. But we still have a problem. It renames the tabs URLs into Russian. After renaming the tabs don't work. How can we make it not to rename the tabs URLs into Russian?

Found the solution:
I change original code
$states = array(-3 => 'all', -2 => 'all open', -1 => 'my open') + _support_states();
to my
$states = array(-6 => 'all', -5 => 'new', -4 => 'active', -3 => 'pending', -1 => 'closed');

jeremy’s picture

Status: Needs review » Needs work

In the soon-to-come 7.x-2.x branch of the support module, states will be provided by http://drupal.org/project/workflow if a controlled workflow is required, or a simple field if not (it doesn't force you to do either).

I'm willing to merge sinasalek's patch into the 7.x-1.x branch, however from -alex-'s feedback it sounds like it's not fully working; moving back to 'needs work'. If those that need this can test and get it fully working and mark it as rtbc that would be very helpful.

sinasalek’s picture

Status: Needs work » Needs review
StatusFileSize
new4.02 KB

I updated the patch to address this issue,
New argument added to _support_states and _support_priorities to preserve names when needed

vacho’s picture

Fail to apply to patch.

RaajLio’s picture

Issue summary: View changes

#34 patch worked well for Priority (it's being translated in the comments upon priority change), but it does not work for State. I've triple-checked the patch code and found nothing.

Same thing happens with other patches (#2, #3 and this one: https://www.drupal.org/node/1373074)

Strange thing is that the translation search interface does find the new keywords to translate once the support text group is added and refreshed, but those are not the strings that actually get my priority terms translated. "Build-in interface" string translations are the ones affecting the module, only found for Priority.

Any ideas? I don't get why priority would work but not state. I'm at loss here.

purencool’s picture

Status: Needs review » Closed (outdated)