Commit 1831e1b6 authored by Dries's avatar Dries

- New locale module thanks to Gerhard, Goba, Marco, Kristjan and others.

  The new locale module provides every functionality on the web interface, so you don't need to edit the configuration files or add columns, when you add a new language. This module is an integration of the old locale and localegettext modules, plus a bunch of logic to parse Gettext Portable Object files (opposed to Machine Object files, as supported by localegettext).

  Note: I made some minor changes to the context-sensitive help texts and to some of the status messages.
parent 8517e17e
......@@ -255,24 +255,46 @@ CREATE TABLE history (
) TYPE=MyISAM;
--
-- Table structure for table 'locales'
-- Table structure for table 'locales_meta'
--
CREATE TABLE locales (
lid int(10) NOT NULL auto_increment,
CREATE TABLE locales_meta (
locale varchar(12) NOT NULL default '',
name varchar(64) NOT NULL default '',
enabled int(2) NOT NULL default '0',
isdefault int(2) NOT NULL default '0',
plurals int(1) NOT NULL default '0',
formula varchar(128) NOT NULL default '',
PRIMARY KEY (locale)
) TYPE=MyISAM;
--
-- Table structure for table 'locales_source'
--
CREATE TABLE locales_source (
lid int(11) NOT NULL auto_increment,
location varchar(128) NOT NULL default '',
string blob NOT NULL,
da blob NOT NULL,
fi blob NOT NULL,
fr blob NOT NULL,
en blob NOT NULL,
es blob NOT NULL,
nl blob NOT NULL,
no blob NOT NULL,
sw blob NOT NULL,
source blob NOT NULL,
PRIMARY KEY (lid)
) TYPE=MyISAM;
--
-- Table structure for table 'locales_target'
--
CREATE TABLE locales_target (
lid int(11) NOT NULL default '0',
translation blob NOT NULL,
locale varchar(12) NOT NULL default '',
plid int(11) NOT NULL default '0',
plural int(1) NOT NULL default '0',
KEY lid (lid),
KEY lang (locale),
KEY plid (plid),
KEY plural (plural)
) TYPE=MyISAM;
--
-- Table structure for table 'menu'
--
......@@ -620,7 +642,7 @@ CREATE TABLE users (
changed int(11) NOT NULL default '0',
status tinyint(4) NOT NULL default '0',
timezone varchar(8) default NULL,
language char(2) NOT NULL default '',
language varchar(12) NOT NULL default '',
picture varchar(255) NOT NULL DEFAULT '',
init varchar(64) default '',
data longtext,
......@@ -723,3 +745,5 @@ INSERT INTO filters VALUES (1,'filter',3,1);
INSERT INTO filters VALUES (2,'filter',1,0);
INSERT INTO filters VALUES (3,'filter',3,0);
INSERT INTO variable (name,value) VALUES ('filter_html_1','i:1;');
INSERT INTO locales_meta (locale, name, enabled, isdefault) VALUES ('en', 'English', '1', '1');
......@@ -242,24 +242,48 @@ CREATE TABLE history (
);
--
-- Table structure for locales
-- Table structure for locales_meta
--
CREATE TABLE locales (
lid SERIAL,
CREATE TABLE locales_meta (
locale varchar(12) NOT NULL default '',
name varchar(64) NOT NULL default '',
enabled int4 NOT NULL default '0',
isdefault int4 NOT NULL default '0',
plurals int4 NOT NULL default '0',
formula varchar(128) NOT NULL default '',
PRIMARY KEY (locale)
);
--
-- Table structure for locales_source
--
CREATE sequence locales_source_lid_seq;
CREATE TABLE locales_source (
lid integer DEFAULT nextval('locales_source_lid_seq'::text) NOT NULL,
location varchar(128) NOT NULL default '',
string text NOT NULL default '',
da text NOT NULL default '',
fi text NOT NULL default '',
fr text NOT NULL default '',
en text NOT NULL default '',
es text NOT NULL default '',
nl text NOT NULL default '',
no text NOT NULL default '',
sw text NOT NULL default '',
source text NOT NULL,
PRIMARY KEY (lid)
);
--
-- Table structure for locales_target
--
CREATE TABLE locales_target (
lid int4 NOT NULL default '0',
translation text NOT NULL,
locale varchar(12) NOT NULL default '',
plid int4 NOT NULL default '0',
plural int4 NOT NULL default '0',
UNIQUE (lid),
UNIQUE (locale),
UNIQUE (plid),
UNIQUE (plural)
);
--
-- Table structure for table 'menu'
--
......@@ -601,7 +625,7 @@ CREATE TABLE users (
changed integer NOT NULL default '0',
status smallint NOT NULL default '0',
timezone varchar(8) default NULL,
language char(2) NOT NULL default '',
language varchar(12) NOT NULL default '',
picture varchar(255) NOT NULL DEFAULT '',
init varchar(64) default '',
data text default '',
......@@ -703,6 +727,7 @@ INSERT INTO filters VALUES (2,'filter',1,0);
INSERT INTO filters VALUES (3,'filter',3,0);
INSERT INTO variable (name,value) VALUES ('filter_html_1','i:1;');
INSERT INTO locales_meta(locale, name, enabled, isdefault) VALUES('en', 'English', '1', '1');
---
--- Functions
......
......@@ -70,7 +70,9 @@
"2004-08-04" => "update_96",
"2004-08-06" => "update_97",
"2004-08-07" => "update_98",
"2004-08-09" => "update_99"
"2004-08-09" => "update_99",
"2004-08-10" => "update_100",
"2004-08-11" => "update_101"
);
function update_32() {
......@@ -1461,6 +1463,87 @@ function update_99() {
return $ret;
}
function update_100() {
$ret = array();
if ($GLOBALS["db_type"] == "mysql") {
$ret[] = update_sql("CREATE TABLE {locales_source} (
lid int(11) NOT NULL auto_increment,
location varchar(128) NOT NULL default '',
source blob NOT NULL,
PRIMARY KEY (lid)
)");
$ret[] = update_sql("CREATE TABLE {locales_target} (
lid int(11) NOT NULL default '0',
translation blob NOT NULL,
locale varchar(12) NOT NULL default '',
plid int(11) NOT NULL default '0',
plural int(1) NOT NULL default '0',
KEY lid (lid),
KEY lang (locale),
KEY plid (plid),
KEY plural (plural)
)");
$ret[] = update_sql("INSERT INTO {locales_meta} (locale, name, enabled, isdefault) VALUES ('en', 'English', '1', '1')");
$ret[] = update_sql("ALTER TABLE {users} CHANGE language language varchar(12) NOT NULL default ''");
}
else { // TODO: pgsql support (see database.pgsql for suggestions)
}
return $ret;
}
function update_101() {
include_once 'includes/locale.inc';
// get the language columns
$result = db_query('SELECT * FROM {locales} LIMIT 1');
$fields = array();
if (db_num_rows($result)) {
$columns = array_keys(db_fetch_array($result));
foreach ($columns as $field) {
$fields[$field] = 1;
}
// but not the fixed fields
unset($fields['lid'], $fields['location'], $fields['string']);
// insert locales
$list = _locale_get_iso639_list();
foreach ($fields as $key => $value) {
if (db_result(db_query("SELECT COUNT(lid) FROM {locales} WHERE $key != ''"))) {
if (isset($list[$key])) {
$name = $list[$key][0];
if ($key == 'en') {
$key = 'en-local';
}
db_query("INSERT INTO {locales_meta} (locale, name) VALUES ('%s', '%s')", $key, $name);
}
else {
db_query("INSERT INTO {locales_meta} (locale, name) VALUES ('%s', '%s')", $key, $key);
}
}
}
// get all strings
$result = db_query('SELECT * FROM {locales}');
while($entry = db_fetch_object($result)) {
// insert string if at least one translation exists
$test = 'return $entry->'. implode(' == "" && $entry->', array_keys($fields)) .' == "";';
if (!eval($test)) {
db_query("INSERT INTO {locales_source} (location, source) VALUES ('%s', '%s')", $entry->location, $entry->string);
$lid = db_fetch_object(db_query("SELECT lid FROM {locales_source} WHERE location = '%s' AND source = '%s'", $entry->location, $entry->string));
foreach ($fields as $key => $value) {
// insert translation if non-empty
db_query("INSERT INTO {locales_target} (lid, translation, locale) VALUES (%d, '%s', '%s')", $lid->lid, $entry->$key, $key);
}
}
}
}
$ret = array();
$ret[] = update_sql("DROP TABLE {locales}");
return $ret;
}
function update_sql($sql) {
$edit = $_POST["edit"];
......
......@@ -505,8 +505,15 @@ function message_na() {
/**
* Initialize the localization system.
*/
function locale_init() {
global $languages, $user;
function locale_initialize() {
global $user;
if (function_exists('locale')) {
$languages = locale_supported_languages();
$languages = $languages['name'];
}
else {
$languages = array();
}
if ($user->uid && $languages[$user->language]) {
return $user->language;
}
......@@ -540,9 +547,10 @@ function locale_init() {
* The translated string.
*/
function t($string, $args = 0) {
global $languages;
$string = ($languages && module_exist('locale') ? locale($string) : $string);
global $locale;
if (function_exists('locale') && $locale != 'en') {
$string = locale($string);
}
if (!$args) {
return $string;
......@@ -841,7 +849,23 @@ function format_rss_item($title, $link, $description, $args = array()) {
* A translated string.
*/
function format_plural($count, $singular, $plural) {
return t($count == 1 ? $singular : $plural, array('%count' => $count));
if ($count == 1) return t($singular);
// get the plural index through the gettext formula
$index = (function_exists('locale')) ? locale_get_plural($count) : -1;
if ($index < 0) { // backward compatibility
return t($plural, array("%count" => $count));
}
else {
switch ($index) {
case "0":
return t($singular);
case "1":
return t($plural, array("%count" => $count));
default:
return t(strtr($plural, array("%count" => '%count['. $index .']')), array('%count['. $index .']' => $count));
}
}
}
/**
......@@ -1814,7 +1838,7 @@ function drupal_eval($code) {
}
// initialize localization system:
$locale = locale_init();
$locale = locale_initialize();
// initialize theme:
$theme = init_theme();
......
......@@ -45,15 +45,6 @@
# If required, update PHP's include path to include your PEAR directory:
// ini_set("include_path", ".:/path/to/pear");
#
# Languages / translation / internationalization:
#
# The first language listed in this associative array will
# automatically become the default language. You can add a language
# but make sure your SQL table, called locales is updated
# appropriately.
$languages = array("en" => "english");
#
# Custom navigation links:
#
......
<?php
// $Id$
/**
* @file
*
* Admin related functions for locale.module
*
*/
// ---------------------------------------------------------------------------------
// Language addition functionality (administration only)
/**
* Helper function to add a language
*/
function _locale_add_language($code, $name, $onlylanguage = TRUE) {
db_query("INSERT INTO {locales_meta} (locale, name) VALUES ('%s','%s')", $code, $name);
$result = db_query("SELECT lid FROM {locales_source}");
while ($string = db_fetch_object($result)) {
db_query("INSERT INTO {locales_target} (lid, locale) VALUES (%d,'%s')", $string->lid, $code);
}
// If only the language was added, and not a PO file import triggered
// the language addition, we need to inform the user on how to start
// a translation
if ($onlylanguage) {
$message = t("'%locale' language added. You can now import a translation. See the <a href=\"%locale-help\">help screen</a> for more information.", array('%locale' => t($name), '%locale-help' => url("admin/help/locale")));
}
else {
$message = t("'%locale' language added.", array('%locale' => t($name)));
}
drupal_set_message($message);
watchdog('locale', t("'%locale' language added.", array('%locale' => $code)));
}
/**
* User interface for the language management screen
*/
function _locale_admin_manage_screen() {
$edit = &$_POST['edit'];
$languages = locale_supported_languages(TRUE, TRUE);
$header = array(array('data' => t('code')), array('data' => t('English name')), array('data' => t('enabled')), array('data' => t('default')), array('data' => t('translated')), array('data' => t('operations')));
foreach ($languages['name'] as $key => $lang) {
$status = db_fetch_object(db_query("SELECT isdefault, enabled FROM {locales_meta} WHERE locale = '%s'", $key));
if ($key == 'en') {
$rows[] = array('en', $lang, form_checkbox('', 'enabled][en', 1, $status->enabled), form_radio('', 'sitedefault', $key, $status->isdefault), message_na(), '');
}
else {
$original = db_fetch_object(db_query("SELECT COUNT(*) AS strings FROM {locales_source}"));
$translation = db_fetch_object(db_query("SELECT COUNT(*) AS translation FROM {locales_target} WHERE locale = '%s' AND translation != ''", $key));
$ratio = ($original->strings > 0 && $translation->translation > 0) ? round(($translation->translation/$original->strings)*100., 2) : 0;
$rows[] = array($key, ($key != 'en' ? form_textfield('', 'name]['. $key, $lang, 15, 64) : $lang), form_checkbox('', 'enabled]['. $key, 1, $status->enabled), form_radio('', 'sitedefault', $key, $status->isdefault), "$translation->translation/$original->strings ($ratio%)", ($key != 'en' ? l(t('delete locale'), 'admin/locale/language/delete/'. urlencode($key)) : ''));
}
}
return form(theme('table', $header, $rows) . form_submit(t('Save configuration')), 'POST', url('admin/locale'));
}
/**
* User interface for the language addition screen
*/
function _locale_admin_manage_add_screen() {
$isocodes = _locale_prepare_iso_list();
$output = '<h2>'. t('From language list') .'</h2>';
$form = form_select(t('Language name'), 'langcode', key($isocodes), $isocodes, t('Select your language here, or add it below, if you are unable to find it.'));
$form .= form_submit(t('Add language'));
$output .= form($form);
$edit = &$_POST['edit'];
$output .= '<h2>'. t('Custom language') .'</h2>';
$form = form_textfield(t('Language code'), 'langcode', $edit['langcode'], 70, 12, t("Commonly this is an <a href=\"%iso-codes\">ISO 639 language code</a> with an optional country code for regional variants. Examples include 'en', 'en-US' and 'zh-cn'.", array("%iso-codes" => "http://www.w3.org/WAI/ER/IG/ert/iso639.htm")));
$form .= form_textfield(t('Language name in English'), 'langname', $edit['langname'], 70, 64, t('Name of the language. Will be availabale for translation in all languages.'));
$form .= form_submit(t('Add language'));
$output .= form($form);
return $output;
}
/**
* User interface for the translation import screen
*/
function _locale_admin_import_screen() {
$languages = locale_supported_languages(FALSE, TRUE);
$languages = array_map("t", $languages['name']);
unset($languages['en']);
if (!count($languages)) {
drupal_set_message(t('You need to have at least one language set up to import translations.'), 'error');
}
else {
$languages = array(
t('Already added languages') => $languages,
t('Languages not yet added') => _locale_prepare_iso_list()
);
$form = form_file(t('Language file'), 'file', 50, t('A gettext Portable Object (.po) file.'));
$form .= form_select(t('Import into'), 'langcode', '', $languages, t('Choose the language you want to add strings into. If you choose a language which is not yet set up, then it will be added.'));
$form .= form_radios(t('Mode'), 'mode', 'overwrite', array("overwrite" => t('Strings in the uploaded file replace existing ones, new ones are added'), "keep" => t('Existing strings are kept, only new strings are added')));
$form .= form_submit(t('Import'));
$output = form($form, 'POST', url('admin/locale/language/import'), array('enctype' => 'multipart/form-data'));
}
return $output;
}
/**
* Parses Gettext Portable Object file information and inserts into database
*
* @param $file Name of local file to be imported
* @param $edit Language code
* @param $mode should existing translations be replaced?
*/
function _locale_import_po($file, $lang, $mode) {
// Check if we have the language already in the database
if (!db_fetch_object(db_query("SELECT locale FROM {locales_meta} WHERE locale = '%s'", $lang))) {
drupal_set_message(t("Unsupported language selected for import."), 'error');
return FALSE;
}
// Check if we can get the strings from the file
if (!($strings = _locale_import_read_po($file))) {
drupal_set_message(t("Translation file broken: Couldn't be read."), 'error');
return FALSE;
}
// Strip out header from the string pairs
$header = $strings[""]["msgstr"];
unset($strings[""]);
// Get information from the header into the database
if ($header) {
$hdr = _locale_import_parse_header($header);
// Get the plural formula
if ($hdr["Plural-Forms"] && $p = _locale_import_parse_plural_forms($hdr["Plural-Forms"])) {
list($nplurals, $plural) = $p;
db_query("UPDATE {locales_meta} SET plurals = '%d', formula = '%s' WHERE locale = '%s'", $nplurals, $plural, $lang);
}
else {
db_query("UPDATE {locales_meta} SET plurals = '%d', formula = '%s' WHERE locale = '%s'", 0, '', $lang);
}
}
else {
drupal_set_message(t("Translation file broken: No header."), 'error');
return FALSE;
}
$fullstr = 0;
foreach ($strings as $value) {
$comments = _locale_import_shorten_comments($value['#']);
// Handle a translation for some plural string
if (strpos($value['msgid'], "\0")) {
$english = explode("\0", $value['msgid'], 2);
$entries = array_keys($value['msgstr']);
for ($i = 3; $i <= count($entries); $i++) {
$english[] = $english[1];
}
$translation = array_map("_locale_import_append_plural", $value['msgstr'], $entries);
$english = array_map("_locale_import_append_plural", $english, $entries);
foreach ($translation as $key => $trans) {
if ($trans != '') {
$fullstr++;
}
$loc = db_fetch_object(db_query("SELECT s.lid, t.translation FROM {locales_source} s LEFT JOIN {locales_target} t ON s.lid = t.lid WHERE s.source = '%s' AND t.locale = '%s'", $english[$key], $lang));
if ($loc->lid) {
$lid = $loc->lid;
db_query("UPDATE {locales_source} SET location = '%s' WHERE lid = %d", $comments, $lid);
}
else {
db_query("INSERT INTO {locales_source} (location, source) VALUES ('%s', '%s')", $comments, $english[$key]);
$lid = db_fetch_object(db_query("SELECT lid FROM {locales_source} WHERE location = '%s' AND source = '%s'", $comments, $english[$key]));
$lid = $lid->lid;
}
if ($key == 0) {
$parent = $lid;
}
if ($loc->translation && $mode == 'overwrite') {
db_query("UPDATE {locales_target} SET translation = '%s', plid = %d, plural = %d WHERE locale = '%s' AND lid = %d", $trans, $parent, $key, $lang, $lid);
}
elseif (!$loc->translation) {
db_query("INSERT INTO {locales_target} (lid, locale, translation, plid, plural) VALUES (%d, '%s', '%s', %d, %d)", $lid, $lang, $trans, $parent, $key);
}
}
}
// A simple translation
else {
$english = $value['msgid'];
$translation = $value['msgstr'];
if ($translation != '') {
$fullstr++;
}
$loc = db_fetch_object(db_query("SELECT s.lid, t.translation FROM {locales_source} s LEFT JOIN {locales_target} t ON s.lid = t.lid WHERE s.source = '%s' AND t.locale = '%s'", $english, $lang));
if ($loc->lid) {
$lid = $loc->lid;
db_query("UPDATE {locales_source} SET location = '%s' WHERE source = '%s'", $comments, $english);
}
else {
db_query("INSERT INTO {locales_source} (location, source) VALUES ('%s', '%s')", $comments, $english);
$loc = db_fetch_object(db_query("SELECT lid FROM {locales_source} WHERE location = '%s' AND source = '%s'", $comments, $english));
$lid = $loc->lid;
}
if ($loc->translation && $mode == 'overwrite') {
db_query("UPDATE {locales_target} SET translation = '%s' WHERE locale = '%s' AND lid = %d", $translation, $lang, $lid);
}
elseif (!$loc->translation) {
db_query("INSERT INTO {locales_target} (lid, locale, translation) VALUES (%d, '%s', '%s')", $lid, $lang, $translation);
}
}
}
// Successfull import
cache_clear_all("locale:$lang");
drupal_set_message(t("Translation successfully imported. %num translated strings added to language.", array('%num' => $fullstr)));
watchdog('locale', strtr("Translation imported into '%locale', %num translated strings added to language.", array('%locale' => $lang, '%num' => $fullstr)));
return TRUE;
}
/**
* Parses Gettext Portable Object file into an array
*
* @param $path Name of local file to parse
* @author Jacobo Tarrio
*/
function _locale_import_read_po($path) {
$fd = fopen($path, "rb");
if (!$fd) {
drupal_set_message(t("Translation import failed: File '%path' cannot be read.", array("%path" => $path)), 'error');
return FALSE;
}
$info = fstat($fd);
$len = $info["size"];
$po = fread($fd, $len);
fclose($fd);
$context = "COMMENT"; // Parser context: COMMENT, MSGID, MSGID_PLURAL, MSGSTR and MSGSTR_ARR
$current = array(); // Current entry being read
$strings = array(); // List of entries read
$plural = 0; // Current plural form
$po = strtr($po, array("\\\n" => ""));
$lines = split("\n", $po);
$lineno = 0;
foreach ($lines as $line) {
$lineno++;
$line = trim($line);
if (!strncmp("#", $line, 1)) { // A comment
if ($context == "COMMENT") { // Already in comment context: add
$current["#"][] = substr($line, 1);
}
elseif (($context == "MSGSTR") || ($context == "MSGSTR_ARR")) { // End current entry, start a new one
$strings[$current["msgid"]] = $current;
$current = array();
$current["#"][] = substr($line, 1);
$context = "COMMENT";
}
else { // Parse error
drupal_set_message(t("Translation file broken: Expected \"msgstr\" in line %lineno", array("%lineno" => $lineno)), 'error');
return FALSE;
}
}
elseif (!strncmp("msgid_plural", $line, 12)) {
if ($context != "MSGID") { // Must be plural form for current entry
drupal_set_message(t("Translation file broken: Unexpected \"msgid_plural\" in line %lineno", array("%lineno" => $lineno)), 'error');
return FALSE;
}
$line = trim(substr($line, 12));
$quoted = _locale_import_parse_quoted($line);
if ($quoted === false) {
drupal_set_message(t("Translation file broken: Syntax error in line %lineno", array("%lineno" => $lineno)), 'error');
return FALSE;
}
$current["msgid"] = $current["msgid"] ."\0". $quoted;
$context = "MSGID_PLURAL";
}
elseif (!strncmp("msgid", $line, 5)) {
if ($context == "MSGSTR") { // End current entry, start a new one
$strings[$current["msgid"]] = $current;
$current = array();
}
elseif ($context == "MSGID") { // Already in this context? Parse error
drupal_set_message(t("Translation file broken: Unexpected \"msgid\" in line %lineno", array("%lineno" => $lineno)), 'error');
return FALSE;
}
$line = trim(substr($line, 5));
$quoted = _locale_import_parse_quoted($line);
if ($quoted === false) {
drupal_set_message(t("Translation file broken: Syntax error in line %lineno", array("%lineno" => $lineno)), 'error');
return FALSE;
}
$current["msgid"] = $quoted;
$context = "MSGID";
}
elseif (!strncmp("msgstr[", $line, 7)) {
if (($context != "MSGID") && ($context != "MSGID_PLURAL") && ($context != "MSGSTR_ARR")) { // Must come after msgid, msgid_plural, or msgstr[]
drupal_set_message(t("Translation file broken: Unexpected \"msgstr[]\" in line %lineno", array("%lineno" => $lineno)), 'error');
return FALSE;
}
if (strpos($line, "]") === false) {
drupal_set_message(t("Translation file broken: Syntax error in line %lineno", array("%lineno" => $lineno)), 'error');
return FALSE;
}
$frombracket = strstr($line, "[");
$plural = substr($frombracket, 1, strpos($frombracket, "]") - 1);
$line = trim(strstr($line, " "));
$quoted = _locale_import_parse_quoted($line);
if ($quoted === false) {
drupal_set_message(t("Translation file broken: Syntax error in line %lineno", array("%lineno" => $lineno)), 'error');
return FALSE;
}
$current["msgstr"][$plural] = $quoted;
$context = "MSGSTR_ARR";
}
elseif (!strncmp("msgstr", $line, 6)) {
if ($context != "MSGID") { // Should come just after a msgid block
drupal_set_message(t("Translation file broken: Unexpected \"msgstr\" in line %lineno", array("%lineno" => $lineno)), 'error');
return FALSE;
}
$line = trim(substr($line, 6));
$quoted = _locale_import_parse_quoted($line);
if ($quoted === false) {
drupal_set_message(t("Translation file broken: Syntax error in line %lineno", array("%lineno" => $lineno)), 'error');
return FALSE;
}
$current["msgstr"] = $quoted;
$context = "MSGSTR";
}
elseif ($line != "") {
$quoted = _locale_import_parse_quoted($line);
if ($quoted === false) {
drupal_set_message(t("Translation file broken: Syntax error in line %lineno", array("%lineno" => $lineno)), 'error');
return FALSE;
}
if (($context == "MSGID") || ($context == "MSGID_PLURAL")) {
$current["msgid"] .= $quoted;
}
elseif ($context == "MSGSTR") {
$current["msgstr"] .= $quoted;
}