First version, not really usable yet.
authorJose Reyero
Thu, 24 Jul 2008 18:40:23 +0000 (18:40 +0000)
committerJose Reyero
Thu, 24 Jul 2008 18:40:23 +0000 (18:40 +0000)
Reworking i18nstrings WIP

experimental/i18ncontent.module
experimental/i18nstrings.module [deleted file]
i18n.module
i18nstrings/i18nstrings.info [moved from experimental/i18nstrings.info with 100% similarity]
i18nstrings/i18nstrings.install [moved from experimental/i18nstrings.install with 74% similarity]
i18nstrings/i18nstrings.module [new file with mode: 0644]

index 0587ab2..1118d95 100644 (file)
  */
 
 /**
+ * Implementation of hook_node_info()
+ * 
  * Returns node types with translated info
  */
 function i18ncontent_node_info() {
   // No db rewrite sql here, so we don't need to worry about our own rewriting
   $type_result = db_query('SELECT nt.type, nt.* FROM {node_type} nt ORDER BY nt.type ASC', 'nt', 'type');
   while ($type = db_fetch_object($type_result)) {
-    $type->name = tt('content_type_name:'.$type->type, $type->name);
-    $type->description = tt('content_type_description:'.$type->type, $type->description);
+    $type->name = tt("nodetype:$type->type:name", $type->name);
+    $type->description = tt("nodetype:$type->type:description", $type->description);
     $info[$type->type] = (array)$type;
   }
 
@@ -25,6 +27,20 @@ function i18ncontent_node_info() {
 }
 
 /**
+ * Implementation of hook_content_type()
+ * 
+ * @todo More fine grained, just update the given node type (not possible when changing type name)
+ */
+function i18ncontent_node_type($op, $info) {
+  switch ($op) {
+    case 'update':
+    case 'insert':
+    case 'delete':
+      i18ncontent_locale_refresh();
+  }
+}
+
+/**
  * Blocks retrieving of normal content types
  */
 function i18ncontent_db_rewrite_sql($query, $primary_table, $primary_key) {
@@ -32,4 +48,38 @@ function i18ncontent_db_rewrite_sql($query, $primary_table, $primary_key) {
     // Using FALSE here doesn't work with older mysql versions
     return array('where' => '0 = 1');
   }
+}
+
+/**
+ * Implementation of hook_locale().
+ */
+function i18ncontent_locale($op = 'groups', $group = NULL) {
+  switch ($op) {
+    case 'groups':
+      return array('nodetype' => t('Content type'));
+    case 'refresh':
+      if ($group == 'nodetype') {
+        return i18ncontent_locale_refresh();
+      }
+  }
+}
+
+/**
+ * Refresh content type strings.
+ * 
+ * @todo Clean up leftover strings
+ */
+function i18ncontent_locale_refresh() {
+  foreach (node_get_types() as $type) {
+    tt("nodetype:$type->type:name", $type->name, NULL, TRUE);
+    tt("nodetype:$type->type:title", $type->title_label, NULL, TRUE);
+    tt("nodetype:$type->type:body", $type->body_label, NULL, TRUE);
+    /*
+    if ($type->help) {
+      ts("nodetype:$type->type:help", $type->help, NULL, TRUE);
+      $type->help = '';
+      node_type_save($type);
+    }
+    */
+  }
 }
\ No newline at end of file
diff --git a/experimental/i18nstrings.module b/experimental/i18nstrings.module
deleted file mode 100644 (file)
index 62fc2bb..0000000
+++ /dev/null
@@ -1,135 +0,0 @@
-<?php
-// $Id$
-
-/**
- * @file
- * Internationalization (i18n) package - translattable strings
- * 
- * @author Jose A. Reyero, 2007
- *
- */
-
-/**
- * Implementation of hook_menu().
- */
-function i18nstrings_menu($may_cache) {
-  $items[] = array(
-      'path' => 'admin/settings/i18n/strings',
-      'type' => MENU_LOCAL_TASK,
-      'title' => t('Strings'),
-      'description' => t('Translatable strings.'),
-      'callback' => 'i18nstrings_admin',
-       'access' => user_access('administer site configuration'),
-  );
-
-  return $items;
-}
-
-/**
- * Menu callback. Administration page
- */
-function i18nstrings_admin($op = NULL, $strid = NULL) {
-  switch($op) {
-    case 'edit':
-      return drupal_get_form('i18nstrings_admin_form', $strid);
-    default:
-      return i18nstrings_admin_overview();
-  }
-}
-
-/**
- * List of strings
- */
-function i18nstrings_admin_overview() {
-  $output = '';
-  $header = array(t('String Id'), t('Default'), '');
-  $result = db_query("SELECT DISTINCT(strid) FROM {i18n_strings} ORDER BY strid", i18n_default_language());
-  $rows = array();
-  while($str = db_fetch_object($result)) {
-    $rows[] = array(
-      $str->strid, 
-      tt($str->strid), 
-      l(t('edit'), 'admin/settings/i18n/strings/edit/'.$str->strid)
-    );
-  }
-  $output .= theme('table', $header, $rows);
-  return $output;
-}
-
-/**
- * Form callback: i18nstrings_admin_form
- */
-function i18nstrings_admin_form($strid) {
-  $strings = i18nstrings_load($strid);
-  $form['strid'] = array('#type' => 'value', '#value' => $strid);
-  $form['languages'] = array('#type' => 'fieldset', '#tree' => TRUE, '#title' => t('Translations'));
-
-  // Approximate the number of rows in a textfield with a maximum of 10.
-  $default = i18nstrings_get_string($strid, i18n_default_language());
-  $rows = min(ceil(str_word_count($default) / 12), 10);
-  
-  foreach (i18n_supported_languages() as $language => $name) {
-    $form['languages'][$language] = array(
-      '#type' => 'textarea',
-      '#rows' => $rows,
-      '#title' => $name,
-      '#default_value' => i18nstrings_get_string($strid, $language)
-    );
-  }
-  $form['submit'] = array('#type' => 'submit', '#value' => t('Save'));
-  return $form;
-}
-
-/**
- * Form submit callback
- */
-function i18nstrings_admin_form_submit($form_id, $form_values) {
-  $strid = $form_values['strid'];
-  foreach (i18n_supported_languages() as $language => $name) {
-    i18nstrings_save_string($strid, $language, $form_values['languages'][$language]);
-  }
-  drupal_set_message(t('The strings have been updated'));
-  return 'admin/settings/i18n/strings';
-}
-
-/**
- * Load string translations
- */
-function i18nstrings_load($strid) {
-  $strings = array();
-  $result = db_query("SELECT * FROM {i18n_strings} WHERE strid = '%s'", $strid);
-  while ($str = db_fetch_object($result)) {
-    $strings[$str->locale] = $str->text;
-  }
-}
-
-/**
- * Get string for a language
- */
-function i18nstrings_get_string($strid, $language) {
-  return db_result(db_query("SELECT text FROM {i18n_strings} WHERE strid = '%s' AND locale = '%s'", $strid, $language));
-}
-
-/**
- * Save string for a language
- */
-function i18nstrings_save_string($strid, $language, $value) {
-  drupal_set_message("DEBUG: i18n_strings_save: $strid($language)= $value");
-  db_query("DELETE FROM {i18n_strings} WHERE strid = '%s' AND locale = '%s'", $strid, $language);
-  db_query("INSERT INTO {i18n_strings}(strid, locale, text) VALUES('%s', '%s', '%s')", $strid, $language, $value);
-}
-/**
- * Translate configurable string
- */
-function tt($strid, $default = NULL, $language = NULL) {
-  $language = $language ? $language : i18n_get_lang();
-  if ($translation = i18nstrings_get_string($strid, $language)) {
-    return $translation;
-  } elseif ($default) {
-    i18nstrings_save_string($strid, $language, $default);
-    return $default;
-  } elseif ($language != i18n_default_language() && $translation = i18nstrings_get_string($strid, i18n_default_language())) {
-    return $translation;
-  } 
-}
\ No newline at end of file
index 984a98a..0d7ba0a 100644 (file)
@@ -356,7 +356,7 @@ function i18n_supported_languages($all = FALSE) {
 }
 
 /**
- * Returns default language
+ * Returns default language code
  */
 function i18n_default_language(){
   return i18n_languages('site_default'); 
@@ -1207,3 +1207,42 @@ function _i18n_set_db_prefix($lang) {
 function _i18n_get_original_path() {
   return isset($_REQUEST["q"]) ? trim($_REQUEST["q"],"/") : '';
 }
+
+/**
+ * String handling functions (Object localization)
+ * 
+ * These are a set of wrapper functions that will call i18nstrings if enabled 
+ * or use plain Drupal core's localization othewise.
+ * 
+ * The differences with the default localization system:
+ * - It will translate strings not from English but from the default language
+ * - They're not plain strings, have some context information too
+ */ 
+
+/**
+ * Translate configurable string, and store for l10n client
+ * 
+ * @param $name
+ *   Textgroup and location glued with ':'
+ * @param $string
+ *   String in default language. Default language may or may not be English
+ * @param $langcode
+ *   Optional language code if different from current request language
+ * @param $update
+ *   Whether to update/create the string
+ */
+function i18n_t($name, $string, $langcode = NULL, $update = FALSE) {
+  global $locale;
+  
+  $langcode = $langcode ? $langcode : $locale;
+  
+  if (function_exists('tt')) {
+    return tt($name, $string, $langcode, $update);
+  } elseif ($langcode == $locale && $langcode != i18n_default_language()) {
+    // Use locale module but only if the language is not the default one
+    // And the language to translate to is the page language
+    $translation = locale($string);
+  } else {
+    return $string;
+  }
+}
\ No newline at end of file
similarity index 74%
rename from experimental/i18nstrings.install
rename to i18nstrings/i18nstrings.install
index 5ddc2bc..b7a24ff 100644 (file)
@@ -6,11 +6,11 @@ function i18nstrings_install() {
     case 'mysql':
     case 'mysqli':
       db_query("
-CREATE TABLE  {i18n_strings} (
-  `strid` varchar(100) NOT NULL,
-  `locale` varchar(12) NOT NULL,
+CREATE TABLE  {i18n_locale} (
+  `strid` varchar(255) NOT NULL,
+  `lid` int(10) NOT NULL,
   `text` text NOT NULL,
-  PRIMARY KEY  (`strid`,`locale`)
+  PRIMARY KEY  (`strid`)
 )  /*!40100 DEFAULT CHARACTER SET UTF8 */ 
 ");
 
@@ -18,4 +18,14 @@ CREATE TABLE  {i18n_strings} (
     default:
       drupal_set_message(t('Database type not supported. This module, i18nstrings, needs manual installation.'));
   }
-}
\ No newline at end of file
+}
+
+/**
+ * Old table
+ *
+CREATE TABLE  {i18n_strings} (
+  `strid` varchar(100) NOT NULL,
+  `locale` varchar(12) NOT NULL,
+  `text` text NOT NULL,
+  PRIMARY KEY  (`strid`,`locale`)
+)  */
\ No newline at end of file
diff --git a/i18nstrings/i18nstrings.module b/i18nstrings/i18nstrings.module
new file mode 100644 (file)
index 0000000..4a6aaab
--- /dev/null
@@ -0,0 +1,217 @@
+<?php
+// $Id$
+
+/**
+ * @file
+ * Internationalization (i18n) package - translattable strings
+ * 
+ * This (rewritten) module uses locale's tables to store source strings in the default language. The storage aims
+ * to be forward compatible with Drupal 6 locale (with textgroups) and i18nstrings 6.x
+ * 
+ * The 'string id' is some context information about the string, has several parts separated by ':'
+ * - textgroup, generic string group name (profile, content_type, etc..)
+ * - object type, like 'field', 'type''
+ * - object id
+ * - property
+ *   
+ * @author Jose A. Reyero, 2007
+ *
+ */
+
+/**
+ * Implementation of hook_menu().
+ */
+function i18nstrings_menu($may_cache) {
+  $items[] = array(
+      'path' => 'admin/settings/i18n/strings',
+      'type' => MENU_LOCAL_TASK,
+      'title' => t('Strings'),
+      'description' => t('Translatable strings.'),
+      'callback' => 'i18nstrings_admin',
+       'access' => user_access('administer site configuration'),
+  );
+
+  return $items;
+}
+
+/**
+ * Menu callback. Administration page
+ */
+function i18nstrings_admin($op = NULL, $strid = NULL) {
+  switch($op) {
+    case 'edit':
+      return drupal_get_form('i18nstrings_admin_form', $strid);
+    default:
+      return i18nstrings_admin_overview();
+  }
+}
+
+/**
+ * List of strings
+ */
+function i18nstrings_admin_overview() {
+  $output = '';
+  $header = array(t('String Id'), t('Default'), '');
+  $result = db_query("SELECT DISTINCT(strid) FROM {i18n_strings} ORDER BY strid", i18n_default_language());
+  $rows = array();
+  while($str = db_fetch_object($result)) {
+    $rows[] = array(
+      $str->strid, 
+      tt($str->strid), 
+      l(t('edit'), 'admin/settings/i18n/strings/edit/'.$str->strid)
+    );
+  }
+  $output .= theme('table', $header, $rows);
+  return $output;
+}
+
+/**
+ * Form callback: i18nstrings_admin_form
+ */
+function i18nstrings_admin_form($strid) {
+  $strings = i18nstrings_load($strid);
+  $form['strid'] = array('#type' => 'value', '#value' => $strid);
+  $form['languages'] = array('#type' => 'fieldset', '#tree' => TRUE, '#title' => t('Translations'));
+
+  // Approximate the number of rows in a textfield with a maximum of 10.
+  $default = i18nstrings_get_string($strid, i18n_default_language());
+  $rows = min(ceil(str_word_count($default) / 12), 10);
+  
+  foreach (i18n_supported_languages() as $language => $name) {
+    $form['languages'][$language] = array(
+      '#type' => 'textarea',
+      '#rows' => $rows,
+      '#title' => $name,
+      '#default_value' => i18nstrings_get_string($strid, $language)
+    );
+  }
+  $form['submit'] = array('#type' => 'submit', '#value' => t('Save'));
+  return $form;
+}
+
+/**
+ * Form submit callback
+ */
+function i18nstrings_admin_form_submit($form_id, $form_values) {
+  $strid = $form_values['strid'];
+  foreach (i18n_supported_languages() as $language => $name) {
+    i18nstrings_save_string($strid, $language, $form_values['languages'][$language]);
+  }
+  drupal_set_message(t('The strings have been updated'));
+  return 'admin/settings/i18n/strings';
+}
+
+/**
+ * Load string translations
+ */
+function i18nstrings_load($strid) {
+  $strings = array();
+  $result = db_query("SELECT * FROM {i18n_strings} WHERE strid = '%s'", $strid);
+  while ($str = db_fetch_object($result)) {
+    $strings[$str->locale] = $str->text;
+  }
+}
+
+/**
+ * Get string for a language
+ */
+function i18nstrings_get_string($strid, $language = FALSE, $refresh = FALSE) {
+  static $strings = array();
+  
+  if ($refresh) {
+    $language ? $strings[$language] = array() : $strings = array(); 
+  }
+  if (!isset($strings[$language][$strid])) {
+    $translation = db_fetch_object(db_query("SELECT t.* FROM {locales_target} t INNER JOIN {locales_source} s ON t.lid = s.lid WHERE s.location = '%s' AND t.locale = '%s'", $strid, $language));
+    $strings[$language][$strid] = $translation ? $translation->translation : FALSE;
+  }
+
+  return $strings[$language][$strid];
+}
+
+/**
+ * Save string for a language
+ * 
+ * Locale's cache needs refreshing after calling this one. We don't do it here as
+ * locale_refresh_cache() is a quite expensive operation.
+ */
+function i18nstrings_save_string($strid, $string) {
+  drupal_set_message("DEBUG: i18n_strings_save: $strid($language)= $value");
+  if ($source = i18nstrings_get_source($strid, $string)) {
+    if ($source->location == $strid && $source->source == $string) {
+      $source->clean = TRUE;
+    } else {
+      $source->clean = FALSE;
+      $source->source = $string;
+      $source->location = $strid;
+    }
+  } else {
+    // String not stored, create a new one
+    $source = new Stdclass();
+    $sorce->source = $string;
+    $source->location = $strid;
+  }
+  // Now save or update, depending on what we've found
+  if (!$source->lid) {
+    //dsm("Creating source string: $strid $string");
+    db_query("INSERT INTO {locales_source} (location, source) VALUES ('%s', '%s')", $source->location, $source->source);
+    $source->lid = db_result(db_query("SELECT lid FROM {locales_source} WHERE location = '%s' AND source = '%s'", $source->location, $source->source));
+  } elseif (!$source->clean) {
+    //dsm("Updating source string: $strid $string");
+    db_query("UPDATE {locales_source} SET location = '%s', source = '%s' WHERE lid = %d", $source->location, $source->source, $source->lid);
+  }
+  return $source;
+}
+
+/**
+ * Get source string from locale system
+ * 
+ * @param $strid
+ *   String id
+ * @param $string
+ *   String in the default language
+ */
+function i18nstrings_get_source($strid, $string) {
+  // First try with string id
+  if ($source = db_fetch_object(db_query("SELECT * FROM {locales_source} WHERE location = '%s'", $strid))) {
+    return $source;
+  } 
+  // Retry with the string itself
+  elseif ($source = db_fetch_object(db_query("SELECT * FROM {locales_source} WHERE source = '%s'", $string))) {
+    return $source;
+  }
+}
+
+/**
+ * Translate configurable string, and store for l10n client
+ * 
+ * @param $strid
+ *   Textgroup and location glued with ':'
+ *   I.e. profile:
+ * @param $default
+ *   String in default language. Default language may or may not be English
+ * @param $langcode
+ *   Optional language code if different from current request language
+ * @param $update
+ *   Whether to update/create the string
+ */
+function tt($strid, $default, $language = NULL, $update = FALSE) {
+  global $locale, $l10n_client_strings;
+  
+  $language = $language ? $language : $locale;
+  $string = NULL;
+  
+  if ($update) {
+    i18nstrings_save_string($strid, $default);
+  }
+  if ($language == i18n_default_language()) {
+    // We just translate from default language, not to default language
+    return $default;
+  } elseif ($translation = i18nstrings_get_string($strid, $language)) {
+    $l10n_client_strings[$default] = $translation;
+    return $translation;
+  } else {
+    $l10n_client_strings[$default] = TRUE;
+    return $default;
+  } 
+}
\ No newline at end of file