Welcome to docs.opsview.com

Opsview Internationalisation

Opsview internationalisation is based upon http://www.catalystframework.org/calendar/2006/18

For Opsview 3.1 and below, the choice of language is specified within the opsview-web/opsview_web.yml file in the langauges: section.

From Opsview 3.3, the choice of language follows these rules:

  • language choice in the lang parameter in the URL (developer use)
  • the contact's choice of language in their user preferences
  • if the contact's choice is “Use browser values”, will be based on the web browser's language values in the Accept-Lang header

The fallback language is i-default, which is English.

All text to be translated with templates (opsview-web/root/….) should be formatted by

c.loc("messages.hostDown [_1]", variable)

See the translators page, for information specifically for translators. The rest of this page is for developers.

Rules

Filtering

  • Assume that the output from c.loc is always the exact string, without any HTML encoding
  • You must filter the localised output string, based on the context of the output. This stops invalid characters from breaking the front end

For HTML text, you should pass through the html filter, eg:

<p>[% c.loc("Some text that might have < or > in it") | html %]</p>

For HTML elements, you should use double quotes for quoting attributes and then pass the string through the html filter, eg,

<select value="[% c.loc("May have some single or double quotes in") | html %]">

For javascript in <script> blocks, you should use single quotes for the string value and pass through an escape_js_string filter, eg:

<script>
var string = '[% c.loc("May have single quotes or \ in it") | escape_js_string %]';
</script>

For javascript in HTML elements, you should use double quotes for quoting the attributes and single quotes for the javascript strings and pass through the escape_js filter and the html filter, eg:

<select onclick=" alert('[% c.loc("May have all sorts of things in it") | escape_js_string | html %]') ">

The escape_js_string filter is in Opsview::Web::View::TT

See http://dev.catalystframework.org/wiki/best_practices for more info on internationalisation.

Message index name

  • Use a keyword for the translation index, rather than the English version (“messages.hostDown” instead of “A host is down”). English then becomes another language. Put these English translations into the i_default.po file, which is used as the basis for all other languages
  • You can have en_gb and en_us files - only put in country specific translations in there
  • Use a dotted namespace for the index, to describe where in the UI the text is (eg, “ui.status.host.menu.editHost” ⇒ “Edit host configuration”, “ui.host.edit.button.submit” ⇒ “Submit” )
  • Judgement required re: duplicated messages (“ui.status.host.menu.editServicecheck” and “ui.status.service.menu.editServicecheck” will be same, so index at “ui.status.menu.editServicecheck”). The longer the actual text, the more likely it is the “same thing”
  • Help or informational text is part of a UI element
  • Separate out UI elements and messages, as messages can be duplicated across the application (“messages.hostDown” ⇒ “A host is down”)

Audit logs

Audit logs are treated slightly differently. Instead of being translated per user, it is a global setting. All audit log entries should go via $c→translate() ( instead of $c→loc() ). We use translate because it is one of the keywords that Locale::Maketext::Extract::Plugin::Perl uses to automatically find suitable method names.

There is an entry in Opsview/Web.pm which puts the usual message through gettext, but uses the i-default language file. This can be changed in future.

The audit log message key should be:

  • messages.auditlog.{area…}.{action}

Eg, messages.auditlog.admin.monitoringserver.movingHostToNewMonitoringserver

Updating translation strings

Make the necessary changes to the template or the controller.

At opsview-web/, run make gettext. This will look for new messages in the templates and controllers and then merge the list with the existing i_default.po language file. It will also syntax check the files and merge in any new strings into all existing PO files but mark the translation as blank.

Edit the language file and commit the changes.

You need to restart opsview-web to view changes to the translation files.

To translate into a different language using Google translate, do these steps:

  • run utils/auto_translate fr - This will take the i_default version, push into Google and get a French version back and update the fr.po file
  • manually look through the file for any inconsistencies. The most common problems are the %1 being changed
  • test by starting up the web server with the new language file
  • move the file into lib/Opsview/Web/I18N/contrib and commit to SVN

When you make changes to translation files, add a comment in the CHANGES file re: new translations required.

Renaming strings

If you have a string that you want to rename the message id for, but leave the string as is, run utils/rename_string “oldstring” “newstring”. This will change the msgid in all po files.

You then have to run make gettext to ensure the files are updated correctly before committing.

New languages

To create a new language translation file, use opsview-web/lib/Opsview/Web/I18N/messages.pot and copy as {languagetag}.po, for instance, es.po for Spanish.

See the translator page for more details on updating the po file.

The first 4 lines of the file should be updated with appropriate comments and then the file should be either committed in svn, posted on the opsview-dev mailing list or raised as a ticket in jira for inclusion within the repository.

Note: If you get the message:

Use of uninitialized value in sprintf at /usr/local/nagios/perl/lib/YAML/Error.pm

This can be ignored.

Guidelines

Admin pages

In the controller config, remove title_description.

In auto, set a title description of the singular for the type:

sub auto : Private {
  my ($self, $c, @args) = @_;
  $c->stash( title_description => $c->loc("ui.objecttype.host") );
  $self->NEXT::auto($c, @args);
}

In list, set a title description of the plural for the type:

sub list :Local :Args(0) {
  my ($self, $c) = @_;
  $c->stash( title_description => $c->loc("ui.admin.host.list.title") );
  $self->NEXT::list($c);
}

Audit logs

Restriction is that audit log entries are in the controller, not the templates.

Must use translate as the method, so that Opsview::Web→translate keeps it in the i_default locale.

$c->translate("messages.auditlog.hostgroup.renameHostgroup [_1] [_2]", $oldname, $newname);

Special cases

Menu entries, menu sections and edit tabs are special cases, as we auto generate the string code:

  • ui.menu.section.{sectionname}
  • ui.menu.entry.{entryname}
  • ui.auto.tab.{tabname}

You have to add an entry in opsview-web/root/dummy for each possible translation, so that the xgettext routine can find these strings.

Menu options

Because menu options can be changed in the yml file, these are based on a valid name already. This name string has spaces removed and is changed to lowercase and then a lookup for ui.menu.entry.{name} is searched. If there is no entry, then it just uses the name in the yml file instead. This allows backwards compatibility with existing menu options.