[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]

[PATCH] Generate locale files on request



---
 loader/lang.c        |   74 +++++++++++++++++++++++++++++++++++++++++++++++++-
 scripts/upd-instroot |   16 +++++------
 2 files changed, 80 insertions(+), 10 deletions(-)

diff --git a/loader/lang.c b/loader/lang.c
index a84c2ec..f3e00df 100644
--- a/loader/lang.c
+++ b/loader/lang.c
@@ -32,6 +32,8 @@
 #include <stdlib.h>
 #include <string.h>
 #include <sys/ioctl.h>
+#include <sys/types.h>
+#include <sys/wait.h>
 #include <unistd.h>
 #include <wchar.h>
 
@@ -224,7 +226,13 @@ static void setLangEnv (int i) {
 /* choice is the index of the chosen language in languages */
 static int setupLanguage(int choice, int forced) {
     char * buf;
+    char *locale_def = NULL;    /* locale lang name */
+    char *locale_charset = NULL;/* locale charset */
+    char *locale_mod = NULL;    /* locale variant */
+    char *locale_p = NULL;      /* last known locale separator */
+    char *locale_i = NULL;      /* string iterator */
     int i;
+    pid_t localedef_pid;
 
     logMessage(DEBUGLVL, "going to set language to %s", languages[choice].lc_all);
     /* load the language only if it is displayable.  if they're using
@@ -241,7 +249,71 @@ static int setupLanguage(int choice, int forced) {
         setLangEnv(english);
 	return 0;
     }
-    
+
+    /* Parse locale parts out of locale name.
+
+      Locale examples:
+      en
+      en_US
+      cz_CS.UTF-8
+      cz_CS UTF-8 latin
+    */
+
+    locale_p = locale_i = languages[choice].lc_all;
+    while (1) {
+        // we found new separator
+        if (*locale_i == '.' || *locale_i == '@' || *locale_i == '\0') {
+            // last separator was annotating charset
+            if (*locale_p == '.') locale_charset = strndup(locale_p + 1, locale_i - locale_p - 1);
+            // last separator was annotating modifier
+            else if (*locale_p == '@') locale_mod = strndup(locale_p + 1, locale_i - locale_p - 1);
+            // there was no known separator last time
+            else locale_def = strndup(locale_p, locale_i - locale_p);
+
+            // save last known separator
+            locale_p = locale_i;
+
+            if(*locale_i == '\0') break; // end of the string
+        }
+
+        // test next character
+        locale_i++;
+    }
+
+    logMessage(DEBUGLVL, "locale %s: base: %s, mod: %s, charset: %s", languages[choice].lc_all, locale_def, locale_mod, locale_charset);
+
+    /* prepare locale name without charset */
+    i = strlen(locale_def);
+    if (locale_mod) i+= strlen(locale_mod) + 1; /* +1 for the @ char */ 
+    locale_p = (char*)calloc(i+1, sizeof(char));
+    locale_p = strcpy(locale_p, locale_def);
+    if (locale_mod){
+        locale_p[strlen(locale_p)] = '@';
+        locale_p = strcat(locale_p, locale_mod);
+    }
+
+    /* generate locale record */
+    logMessage(INFO, "going to prepare locales for %s (locale: %s, charset: %s)", languages[choice].lc_all, locale_p, locale_charset);
+    if ((localedef_pid = fork()) == 0) {
+        execl("/usr/bin/localedef", "localedef",
+              "-i", locale_p,
+              "-f", (locale_charset) ? locale_charset : "UTF-8",
+              languages[choice].lc_all, NULL);
+        exit(254);
+    }
+
+    if (localedef_pid < 0) logMessage(ERROR, "failed forking localedef for %s", languages[choice].lc_all);
+    else{
+        waitpid(localedef_pid, &i, 0);
+        if (WEXITSTATUS(i) != 0) logMessage(ERROR, "failed preparing locales %s [%d]", languages[choice].lc_all, WEXITSTATUS(i));
+    }
+
+    /* cleanup */
+    if (locale_charset) free(locale_charset);
+    if (locale_def) free(locale_def);
+    if (locale_mod) free(locale_mod);
+    if (locale_p) free(locale_p);
+
     setLangEnv (choice);
     isysLoadFont();
 
diff --git a/scripts/upd-instroot b/scripts/upd-instroot
index 5c8d5b5..2b2fc4a 100755
--- a/scripts/upd-instroot
+++ b/scripts/upd-instroot
@@ -634,6 +634,7 @@ usr/bin/hmount
 usr/bin/humount
 usr/bin/killall
 usr/bin/logger
+usr/bin/localedef
 usr/bin/lsattr*
 usr/bin/maketilo
 usr/bin/md5sum
@@ -754,6 +755,7 @@ usr/share/hwdata/pci.ids
 usr/share/hwdata/usb.ids
 usr/share/hwdata/videoaliases
 usr/share/hwdata/videodrivers
+usr/share/i18n
 usr/share/icons/hicolor/*/apps/nm-*
 usr/share/icons/hicolor/index.theme
 usr/share/locale/*/LC_MESSAGES/anaconda.mo
@@ -1113,10 +1115,13 @@ chmod 04755 $DEST/usr/libexec/polkit-1/polkit-agent-helper-1
 chown root:dbus $DEST/$LIBDIR/dbus-1/dbus-daemon-launch-helper
 chmod 04750 $DEST/$LIBDIR/dbus-1/dbus-daemon-launch-helper
 
-# Remove locales unused during the install
+# Generate default locale in case runtime doesn't work
+# /usr/share/i18n/ contains sources
 install -m 644 $DEST/usr/share/anaconda/lang-table $DEST/etc/lang-table
+rm -f $DEST/usr/lib/locale/locale-archive
 localedef -c -i en_US -f UTF-8 --prefix $DEST en_US
 
+# Remove unsupported translations
 cat $DEST/usr/share/anaconda/lang-table* | awk '
 { gsub("-", "", $4);
   print $4;
@@ -1135,14 +1140,7 @@ for p in lib share; do (
     }
 ); done
 
-# Now shrink the locale-archive to contain just the minimum.
-localedef --prefix $DEST --list-archive > $DEST/locales.glibc
-LC_ALL=C unsupported="$(comm -13 $DEST/locales $DEST/locales.glibc)"
-localedef --prefix $DEST --delete-from-archive $unsupported
-mv $DEST/usr/lib/locale/locale-archive $DEST/usr/lib/locale/locale-archive.tmpl
-/usr/sbin/chroot $DEST /usr/sbin/build-locale-archive
-
-rm -f $DEST/locales $DEST/locales.list $DEST/locales.glibc
+rm -f $DEST/locales $DEST/locales.list
 
 # fix up some links for man page related stuff
 for file in nroff groff iconv geqn gtbl gpic grefer ; do
-- 
1.7.4


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]