]> gitweb.fperrin.net Git - Dictionary.git/commitdiff
go
authorThad Hughes <thad.hughes@gmail.com>
Fri, 23 Jul 2010 21:21:07 +0000 (14:21 -0700)
committerThad Hughes <thad.hughes@gmail.com>
Fri, 23 Jul 2010 21:21:07 +0000 (14:21 -0700)
.classpath
AndroidManifest.xml
default.properties
res/values-de/strings.xml
res/values/strings.xml
src/com/hughes/android/dictionary/Dictionary.java
src/com/hughes/android/dictionary/DictionaryActivity.java
src/com/hughes/android/dictionary/DictionaryActivityTest.java
src/com/hughes/android/dictionary/Entry.java [changed mode: 0755->0644]
src/com/hughes/android/dictionary/Language.java

index 64688433c0ce2674013b969a3b3d3c2ce020fc01..b198e6b1160b70d00a10ac1695ca98fd2efe570b 100644 (file)
@@ -4,6 +4,6 @@
        <classpathentry kind="src" path="gen"/>
        <classpathentry kind="con" path="com.android.ide.eclipse.adt.ANDROID_FRAMEWORK"/>
        <classpathentry exported="true" kind="lib" path="jars/icu4j-4_2_1-src/icu4j.jar"/>
-       <classpathentry combineaccessrules="false" kind="src" path="/Util"/>
+       <classpathentry combineaccessrules="false" exported="true" kind="src" path="/Util"/>
        <classpathentry kind="output" path="bin"/>
 </classpath>
index 8c2d06332885c7a29017f3a52b5f3a0630534c94..5bff2e3ec1c51bd2205518e03e1c4696f2c7c4cc 100644 (file)
@@ -3,8 +3,14 @@
 <manifest 
     xmlns:android="http://schemas.android.com/apk/res/android"
     package="com.hughes.android.dictionary" 
-    android:versionCode="1"
-    android:versionName="1.0">
+    android:versionCode="8"
+    android:versionName="1.8">
+
+  <uses-sdk android:minSdkVersion="4" />
+  
+  <uses-permission android:name="android.permission.INTERNET"/>
+  <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
+  <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
 
  <application android:icon="@drawable/icon" android:label="@string/app_name">
  
    </intent-filter>
   </activity>
 
+  <activity android:name="AboutActivity"/>
+  <activity android:name="PreferenceActivity"/>
+  <activity android:name="DownloadActivity"/>
+  <activity android:name="NoDictionaryActivity"/>
+
  </application>
 
 </manifest> 
\ No newline at end of file
index 19c96655d772aa6da4be76417b997aa63fa6cfcb..a1ef8e9ff47020568453aecb2452fa624961b326 100644 (file)
@@ -10,4 +10,4 @@
 # Indicates whether an apk should be generated for each density.
 split.density=false
 # Project target.
-target=android-4
+target=android-3
index a8d07b5cfc97e814d86e37d87ab04ac3c8ce1994..a9b4a7afed9fdf3101996409fc8a6f3bed27cdcc 100755 (executable)
@@ -14,9 +14,7 @@
   <string name="failedAddingToWordList">Fehler bei Wortliste hinzufugen: %s</string>
 
        <!-- About. -->
-       <string name="thadHughes">Thad Hughes</string>
        <string name="contactMe">Wenn QuickDic dir gefällt, würde ich gern von dir hören.  Bitte schicke Bemerkungen, Aufforderungen, oder Programmfehler an:</string>
-       <string name="myEmail">thad.hughes+quickdic@gmail.com</string>
        <string name="currentDictInfo">Wörterbuch Info:</string>
        <string name="noDictLoaded">Kein Wörterbuch geöffnet.</string>
   <string name="aboutText"><![CDATA[%s\n
@@ -44,7 +42,7 @@ Einträgezahl: %d\n
        <string name="wordListFileKey">wordListFile</string>
        <string name="wordListFileTitle">Wortliste Datei</string>
        <string name="wordListFileSummary">Die Datei, in der neue Worte hinzugefügt werden.</string>
-       <string name="wordListFileDefault">/sdcard/wordList.txt</string>
+       <string name="wordListFileDefault">/sdcard/quickdic/wordList.txt</string>
 
   <string name="saveOnlyFirstSubentryKey">saveOnlyFirstSubentry</string>
   <string name="saveOnlyFirstSubentryTitle">Save only first sub-entry</string>
@@ -57,11 +55,11 @@ Einträgezahl: %d\n
        <string name="dictFileKey">dictFile</string>
        <string name="dictFileTitle">Wörterbuch Datei</string>
        <string name="dictFileSummary">Die Datei, die das Wörterbuch enthält (und worein das Wörterbuch heruntergeladen wird).</string>
-       <string name="dictFileDefault">/sdcard/de-en.dict</string>
+       <string name="dictFileDefault">/sdcard/quickdic/de-en.dict</string>
 
        <string name="dictFetchUrlKey">dictFetchUrl</string>
        <string name="dictFetchUrlTitle">Wörterbuch URL</string>
        <string name="dictFetchUrlSummary">Das URL, wovon das Wörterbuch heruntergeladen wird.</string>
-       <string name="dictFetchUrlDefault">http://www.stanford.edu/~egirard/dict/de-en.dict</string>
+       <string name="dictFetchUrlDefault">http://www.stanford.edu/~egirard/dict/de-en_2.0.dict</string>
        
 </resources>
index ada99cbd26ed7d25406c4d686ceaa7162495fda6..3b2e929233aa502a75dc8cef8952626a265e077f 100644 (file)
   <string name="failedAddingToWordList">Failure adding to word list: %s</string>
 
        <!-- About. -->
-       <string name="titleWithVersion">QuickDic 1.8</string>
+       <string name="titleWithVersion">QuickDic 2.0</string>
        <string name="thadHughes">Thad Hughes</string>
        <string name="contactMe">If you\'re using QuickDic, I\'d love to hear from you.  Please send comments, suggestions, bug reports, or just a quick hello to:</string>
-       <string name="myEmail">thad.hughes+quickdic@gmail.com</string>
+       <string name="myEmail">thad.hughes\+quickdic@gmail.com</string>
        <string name="currentDictInfo">Current dictionary info:</string>
        <string name="noDictLoaded">No dictionary loaded.</string>
   <string name="aboutText"><![CDATA[%s\n
index dfca94617d2327b67a307c48436ffada79dbd9af..d8fd3c6b3bd95d6bc8e5d7e1cc806d4ca7944cbb 100755 (executable)
@@ -16,39 +16,44 @@ import com.hughes.util.raf.UniformFileList;
 \r
 public final class Dictionary implements RAFSerializable<Dictionary> {\r
   \r
-  private static final String VERSION_CODE = "DictionaryVersion=1.5";\r
+  private static final String VERSION_CODE = "DictionaryVersion=2.0";\r
 \r
-  static final RAFSerializer<Entry> ENTRY_SERIALIZER = new RAFSerializableSerializer<Entry>(\r
-      Entry.RAF_FACTORY);\r
+  static final RAFSerializer<SimpleEntry> ENTRY_SERIALIZER = new RAFSerializableSerializer<SimpleEntry>(\r
+      SimpleEntry.RAF_FACTORY);\r
   static final RAFSerializer<Row> ROW_SERIALIZER = new RAFSerializableSerializer<Row>(\r
       Row.RAF_FACTORY);\r
   static final RAFSerializer<IndexEntry> INDEX_ENTRY_SERIALIZER = new RAFSerializableSerializer<IndexEntry>(\r
       IndexEntry.RAF_FACTORY);\r
 \r
   final String dictionaryInfo;\r
+  final List<String> sources;\r
   final List<Entry> entries;\r
   final LanguageData[] languageDatas = new LanguageData[2];\r
 \r
   public Dictionary(final String dictionaryInfo, final Language language0, final Language language1) {\r
     this.dictionaryInfo = dictionaryInfo;\r
-    languageDatas[0] = new LanguageData(this, language0, Entry.LANG1);\r
-    languageDatas[1] = new LanguageData(this, language1, Entry.LANG2);\r
+    sources = new ArrayList<String>();\r
+    languageDatas[0] = new LanguageData(this, language0, SimpleEntry.LANG1);\r
+    languageDatas[1] = new LanguageData(this, language1, SimpleEntry.LANG2);\r
     entries = new ArrayList<Entry>();\r
   }\r
 \r
   public Dictionary(final RandomAccessFile raf) throws IOException {\r
     dictionaryInfo = raf.readUTF();\r
+    sources = new ArrayList<String>(FileList.create(raf, RAFSerializer.STRING, raf.getFilePointer()));\r
     entries = CachingList.create(FileList.create(raf, ENTRY_SERIALIZER, raf\r
         .getFilePointer()), 10000);\r
-    languageDatas[0] = new LanguageData(this, raf, Entry.LANG1);\r
-    languageDatas[1] = new LanguageData(this, raf, Entry.LANG2);\r
-    if (!VERSION_CODE.equals(raf.readUTF())) {\r
-      throw new IOException("Invalid dictionary version, expected: " + VERSION_CODE);\r
+    languageDatas[0] = new LanguageData(this, raf, SimpleEntry.LANG1);\r
+    languageDatas[1] = new LanguageData(this, raf, SimpleEntry.LANG2);\r
+    final String version = raf.readUTF();\r
+    if (!VERSION_CODE.equals(version)) {\r
+      throw new IOException("Invalid dictionary version, found " + version + ", expected: " + VERSION_CODE);\r
     }\r
   }\r
 \r
   public void write(RandomAccessFile raf) throws IOException {\r
     raf.writeUTF(dictionaryInfo);\r
+    FileList.write(raf, sources, RAFSerializer.STRING);\r
     FileList.write(raf, entries, ENTRY_SERIALIZER);\r
     languageDatas[0].write(raf);\r
     languageDatas[1].write(raf);\r
index 05f292a9a2e4729aec74dc375eff39bcf1612563..e8d188f4b9974adb5442f3962d980e4b9c9dfc21 100644 (file)
@@ -212,8 +212,8 @@ public class DictionaryActivity extends ListActivity {
       throw new Exception(e);
     }
     
-    final byte lang = prefs.getInt(PREF_DICT_ACTIVE_LANG, Entry.LANG1) == Entry.LANG1 ? Entry.LANG1
-        : Entry.LANG2;
+    final byte lang = prefs.getInt(PREF_DICT_ACTIVE_LANG, SimpleEntry.LANG1) == SimpleEntry.LANG1 ? SimpleEntry.LANG1
+        : SimpleEntry.LANG2;
     
     languageList = new LanguageListAdapter(dictionary.languageDatas[lang]);
     setListAdapter(languageList);
@@ -350,7 +350,7 @@ public class DictionaryActivity extends ListActivity {
   @Override
   public boolean onPrepareOptionsMenu(final Menu menu) {
     switchLanguageMenuItem.setTitle(getString(R.string.switchToLanguage,
-        dictionary.languageDatas[Entry
+        dictionary.languageDatas[SimpleEntry
             .otherLang(languageList.languageData.lang)].language.symbol));
     return super.onPrepareOptionsMenu(menu);
   }
@@ -592,7 +592,7 @@ public class DictionaryActivity extends ListActivity {
       // Entry row(s).
       final TableLayout result = new TableLayout(parent.getContext());
 
-      final Entry entry = dictionary.entries.get(row.getIndex());
+      final SimpleEntry entry = dictionary.entries.get(row.getIndex());
       final int rowCount = entry.getRowCount();
       for (int r = 0; r < rowCount; ++r) {
         final TableRow tableRow = new TableRow(result.getContext());
@@ -604,13 +604,13 @@ public class DictionaryActivity extends ListActivity {
 
         if (r > 0) {
           final TextView spacer = new TextView(tableRow.getContext());
-          spacer.setText(r == 0 ? "\95 " : " \95 ");
+          spacer.setText(r == 0 ? "� " : " � ");
           tableRow.addView(spacer);
         }
         tableRow.addView(column1, layoutParams);
         if (r > 0) {
           final TextView spacer = new TextView(tableRow.getContext());
-          spacer.setText(r == 0 ? "\95 " : " \95 ");
+          spacer.setText(r == 0 ? "� " : " � ");
           tableRow.addView(spacer);
         }
         tableRow.addView(column2, layoutParams);
@@ -632,7 +632,7 @@ public class DictionaryActivity extends ListActivity {
         }
 
         column2.setText(
-            entry.getAllText(Entry.otherLang(languageData.lang))[r],
+            entry.getAllText(SimpleEntry.otherLang(languageData.lang))[r],
             TextView.BufferType.NORMAL);
 
         result.addView(tableRow);
index ea6b692906343da6b481576cde1e3b2310435cae..1ac9e8b0d630dcc59a07ffb220f22dddc655cf9d 100755 (executable)
@@ -43,10 +43,10 @@ public class DictionaryActivityTest extends ActivityInstrumentationTestCase2<Dic
   public void resetDictionary() throws Exception {\r
     final DictionaryActivity dict = getActivity();\r
     \r
-    if (dict.languageList.languageData.language == Language.EN) {\r
+    if (dict.languageList.languageData.language == Language.en) {\r
       postAndWait(switchLangRunnable());\r
     }\r
-    assertEquals(Language.DE, dict.languageList.languageData.language);\r
+    assertEquals(Language.de, dict.languageList.languageData.language);\r
 \r
     postAndWait(new NotifyRunnable() {\r
       protected void run2() {\r
@@ -63,11 +63,11 @@ public class DictionaryActivityTest extends ActivityInstrumentationTestCase2<Dic
     final NotifyRunnable switchLang = switchLangRunnable();\r
 \r
     postAndWait(switchLang);\r
-    assertEquals(Language.EN, dict.languageList.languageData.language);\r
+    assertEquals(Language.en, dict.languageList.languageData.language);\r
     assertEquals("EN", dict.langButton.getText().toString());\r
 \r
     postAndWait(switchLang);\r
-    assertEquals(Language.DE, dict.languageList.languageData.language);\r
+    assertEquals(Language.de, dict.languageList.languageData.language);\r
     assertEquals("DE", dict.langButton.getText().toString());\r
     \r
     dict.finish();\r
old mode 100755 (executable)
new mode 100644 (file)
index 5d1a2d9..fb95f4c
-package com.hughes.android.dictionary;\r
-\r
-import java.io.IOException;\r
-import java.io.RandomAccessFile;\r
-import java.util.ArrayList;\r
-import java.util.Arrays;\r
-import java.util.LinkedHashMap;\r
-import java.util.LinkedHashSet;\r
-import java.util.List;\r
-import java.util.Map;\r
-import java.util.Set;\r
-import java.util.regex.Matcher;\r
-import java.util.regex.Pattern;\r
-\r
-import com.hughes.util.raf.RAFFactory;\r
-import com.hughes.util.raf.RAFSerializable;\r
-\r
-public final class Entry implements RAFSerializable<Entry> {\r
-\r
-  static final byte LANG1 = 0;\r
-  static final byte LANG2 = 1;\r
-\r
-  static final Pattern lineSplitPattern = Pattern.compile("\\s::\\s");\r
-  static final Pattern sublineSplitPattern = Pattern.compile("\\s\\|\\s");\r
-\r
-  final String[] lang1;\r
-  final String[] lang2;\r
-  \r
-//  public Entry(final String lang1, final String lang2) {\r
-//    this.lang1 = new String[] {lang1};\r
-//    this.lang2 = new String[] {lang2};\r
-//  }\r
-\r
-  Entry(final String[] lang1, final String[] lang2) {\r
-    this.lang1 = lang1;\r
-    this.lang2 = lang2;\r
-  }\r
-\r
-  public static final RAFFactory<Entry> RAF_FACTORY = new RAFFactory<Entry>() {\r
-    public Entry create(RandomAccessFile raf) throws IOException {\r
-      final int rows = raf.readByte();\r
-      final String[] lang1 = new String[rows];\r
-      final String[] lang2 = new String[rows];\r
-      for (int i = 0; i < lang1.length; ++i) {\r
-        lang1[i] = raf.readUTF();\r
-        lang2[i] = raf.readUTF();\r
-      }\r
-      return new Entry(lang1, lang2);\r
-    }};\r
-  public void write(RandomAccessFile raf) throws IOException {\r
-    assert lang1.length == (byte) lang1.length;\r
-    raf.writeByte(lang1.length);\r
-    for (int i = 0; i < lang1.length; ++i) {\r
-      raf.writeUTF(lang1[i]);\r
-      raf.writeUTF(lang2[i]);\r
-    }\r
-  }\r
-\r
-  @Override\r
-  public boolean equals(Object o) {\r
-    if (!(o instanceof Entry)) {\r
-      return false;\r
-    }\r
-    final Entry that = (Entry) o;\r
-    return Arrays.deepEquals(this.lang1, that.lang1) && Arrays.deepEquals(this.lang2, that.lang2); \r
-  }\r
-\r
-  @Override\r
-  public int hashCode() {\r
-    return Arrays.deepHashCode(lang1) + Arrays.deepHashCode(lang2);\r
-  }\r
-\r
-  @Override\r
-  public String toString() {\r
-    return getRawText(false);\r
-  }\r
-\r
-  public int getRowCount() {\r
-    assert lang1.length == lang2.length;\r
-    return lang1.length;\r
-  }\r
-\r
-  String[] getAllText(final byte lang) {\r
-    if (lang == LANG1) {\r
-      return lang1;\r
-    }\r
-    assert lang == LANG2;\r
-    return lang2;\r
-  }\r
-  \r
-  String getRawText(boolean onlyFirstSubentry) {\r
-    final StringBuilder result = new StringBuilder();\r
-    for (int i = 0; i < (onlyFirstSubentry ? 1 : lang1.length); ++i) {\r
-      result.append(i == 0 ? "" : " | ").append(lang1[i]);\r
-    }\r
-    result.append("\t");\r
-    for (int i = 0; i < (onlyFirstSubentry ? 1 : lang2.length); ++i) {\r
-      result.append(i == 0 ? "" : " | ").append(lang2[i]);\r
-    }\r
-    return result.toString();\r
-  }\r
-  \r
-  static byte otherLang(final byte lang) {\r
-    assert lang == LANG1 || lang == LANG2;\r
-    return lang == LANG1 ? LANG2 : LANG1;\r
-  }\r
-  \r
-/*\r
-Lu     Letter, Uppercase\r
-Ll  Letter, Lowercase\r
-Lt  Letter, Titlecase\r
-Lm  Letter, Modifier\r
-Lo  Letter, Other\r
-Mn  Mark, Nonspacing\r
-Mc  Mark, Spacing Combining\r
-Me  Mark, Enclosing\r
-Nd  Number, Decimal Digit\r
-Nl  Number, Letter\r
-No  Number, Other\r
-Pc  Punctuation, Connector\r
-Pd  Punctuation, Dash\r
-Ps  Punctuation, Open\r
-Pe  Punctuation, Close\r
-Pi  Punctuation, Initial quote (may behave like Ps or Pe depending on usage)\r
-Pf  Punctuation, Final quote (may behave like Ps or Pe depending on usage)\r
-Po  Punctuation, Other\r
-Sm  Symbol, Math\r
-Sc  Symbol, Currency\r
-Sk  Symbol, Modifier\r
-So  Symbol, Other\r
-Zs  Separator, Space\r
-Zl  Separator, Line\r
-Zp  Separator, Paragraph\r
-*/\r
-\r
-  static Pattern htmlDecimalCode = Pattern.compile("&#([0-9]+);");\r
-  static Pattern htmlCode = Pattern.compile("&#[^;]+;");\r
-  \r
-  static Entry parseFromLine(String line, final boolean hasMultipleSubentries) {\r
-    \r
-    line = line.replaceAll("&lt;", "<");\r
-    line = line.replaceAll("&gt;", ">");\r
-    Matcher matcher;\r
-    while ((matcher = htmlDecimalCode.matcher(line)).find()) {\r
-      final int intVal = Integer.parseInt(matcher.group(1));\r
-      final String charCode = "" + ((char) intVal);\r
-      System.out.println("Replacing " + matcher.group() + " with " + charCode);\r
-      line = matcher.replaceAll(charCode);\r
-    }\r
-    if ((matcher = htmlCode.matcher(line)).find()) {\r
-      System.err.println("HTML code: " + matcher.group());\r
-    }\r
-    \r
-    final String[] parts = lineSplitPattern.split(line);\r
-    if (parts.length != 2) {\r
-      System.err.println("Entry:" + "Invalid line: " + line);\r
-      return null;\r
-    }\r
-    if (!hasMultipleSubentries) {\r
-      return new Entry(new String[] {parts[0].trim()}, new String[] {parts[1].trim()});\r
-    }\r
-    \r
-    final String[] lang1 = sublineSplitPattern.split(" " + parts[0].trim() + " ");\r
-    final String[] lang2 = sublineSplitPattern.split(" " + parts[1].trim() + " ");\r
-    if (lang1.length != lang2.length) {\r
-      System.err.println("Entry:" + "Invalid subline: " + line);\r
-      return null;\r
-    }\r
-    for (int i = 0; i < lang1.length; ++i) {\r
-      lang1[i] = lang1[i].trim();\r
-      lang2[i] = lang2[i].trim();\r
-    }\r
-    return new Entry(lang1, lang2);\r
-  }\r
-  \r
-  static final Map<String, String> bracketToClose = new LinkedHashMap<String, String>();\r
-  static {\r
-    bracketToClose.put("\"", "\"");\r
-    bracketToClose.put(" '", "' ");\r
-  }\r
-  \r
-  // This used to be called WHITESPACE.\r
-  static final Pattern NON_TOKEN_CHAR = Pattern.compile("\\s+");\r
-  \r
-  public Set<String> getIndexableTokens(final byte lang) {\r
-    final Set<String> result = new LinkedHashSet<String>();\r
-    String text = " ";\r
-    for (final String subentry : getAllText(lang)) {\r
-      text += subentry + " ";\r
-    }\r
-\r
-    text = text.replaceAll("fig\\.", " ");\r
-    text = text.replaceAll("\\{[^\\}]+}", " ");\r
-    text = text.replaceAll("\"-", "-");\r
-    text = text.replaceAll("-\"", "-");\r
-    text = text.replaceAll("[\"/\\()<>\\[\\],;?!.]", " ");\r
-    text = text.replaceAll("[-:] ", " ");\r
-    text = text.replaceAll(" [-:]", " ");\r
-    \r
-    // Now be really conservative about what we allow inside a token:\r
-    // See: http://unicode.org/Public/UNIDATA/UCD.html#General_Category_Values\r
-    text = text.replaceAll("[^-:\\p{L}\\p{N}\\p{S}]", " ");\r
-    result.addAll(Arrays.asList(NON_TOKEN_CHAR.split(text)));\r
-\r
-    text = text.replaceAll("[-]", " ");\r
-    result.addAll(Arrays.asList(NON_TOKEN_CHAR.split(text)));\r
-    \r
-    final Set<String> result2 = new LinkedHashSet<String>();\r
-    for (final String token : result) {\r
-      if (isIndexable(token)) {\r
-        result2.add(token);\r
-      }\r
-    }\r
-    return result2;\r
-  }\r
-\r
-  static boolean isIndexable(final String text) {\r
-    // Does it have an alpha-numeric anywhere?\r
-    return text.matches(".*\\w.*");\r
-  }\r
-  \r
-  static List<String> getTextInside(final String text, final String start, final String end) {\r
-    final List<String> result = new ArrayList<String>();\r
-    int startPos = 0;\r
-    while ((startPos = text.indexOf(start)) != -1) {\r
-      final int endPos = text.indexOf(end, startPos + 1);\r
-      result.add(text.substring(startPos + 1, endPos));\r
-      startPos = endPos + 1;\r
-    }\r
-    return result;\r
-  }\r
-\r
-}
\ No newline at end of file
+package com.hughes.android.dictionary;
+
+import java.io.IOException;
+import java.io.RandomAccessFile;
+
+import com.hughes.util.raf.RAFFactory;
+import com.hughes.util.raf.RAFSerializable;
+
+public abstract class Entry implements RAFSerializable<Entry> {
+  
+  public static final RAFFactory<Entry> RAF_FACTORY = new RAFFactory<Entry>() {
+    public Entry create(RandomAccessFile raf) throws IOException {
+      final byte type = raf.readByte();
+      switch (type) {
+      case 0:
+        return SimpleEntry.RAF_FACTORY.create(raf);
+      }
+      throw new RuntimeException("Invalid entry type: " + type);
+    }};
+    
+  
+}
index 0c4b2c5f0f325fc84af0c75b5b8dd9e70fddfdf8..0f53d7ff4f0fe90700145a315402935d1f4af2fe 100755 (executable)
@@ -9,6 +9,9 @@ import com.ibm.icu.text.Collator;
 \r
 public class Language {\r
 \r
+  static final Map<String, Language> symbolToLangauge = new LinkedHashMap<String, Language>();\r
+\r
+  \r
   final String symbol;\r
   final Locale locale;\r
 \r
@@ -18,8 +21,8 @@ public class Language {
   private Collator findCollator;\r
   final Comparator<String> findComparator;\r
 \r
-  public Language(final String symbol, final Locale locale) {\r
-    this.symbol = symbol;\r
+  public Language(final Locale locale) {\r
+    this.symbol = locale.getLanguage();\r
     this.locale = locale;\r
 \r
     this.sortComparator = new Comparator<String>() {\r
@@ -33,7 +36,8 @@ public class Language {
         return getFindCollator().compare(textNorm(s1), textNorm(s2));\r
       }\r
     };\r
-\r
+    \r
+    symbolToLangauge.put(symbol.toLowerCase(), this);\r
   }\r
 \r
   public String textNorm(final String s) {\r
@@ -42,6 +46,10 @@ public class Language {
 \r
   @Override\r
   public String toString() {\r
+    return locale.toString();\r
+  }\r
+  \r
+  public String getSymbol() {\r
     return symbol;\r
   }\r
   \r
@@ -65,9 +73,11 @@ public class Language {
 \r
   // ----------------------------------------------------------------\r
 \r
-  public static final Language EN = new Language("EN", Locale.ENGLISH);\r
+  public static final Language en = new Language(Locale.ENGLISH);\r
+  public static final Language fr = new Language(Locale.FRENCH);\r
+  public static final Language it = new Language(Locale.ITALIAN);\r
 \r
-  public static final Language DE = new Language("DE", Locale.GERMAN) {\r
+  public static final Language de = new Language(Locale.GERMAN) {\r
     @Override\r
     public String textNorm(String token) {\r
       boolean sub = false;\r
@@ -82,28 +92,29 @@ public class Language {
       if (!sub) {\r
         return token;\r
       }\r
-      token = token.replaceAll("ae", "ä");\r
-      token = token.replaceAll("oe", "ö");\r
-      token = token.replaceAll("ue", "ü");\r
-\r
-      token = token.replaceAll("Ae", "Ä");\r
-      token = token.replaceAll("Oe", "Ö");\r
-      token = token.replaceAll("Ue", "Ü");\r
-      return token;\r
+      token = token.replaceAll("ae", "ä");\r
+      token = token.replaceAll("oe", "ö");\r
+      token = token.replaceAll("ue", "ü");\r
+\r
+      token = token.replaceAll("Ae", "Ä");\r
+      token = token.replaceAll("Oe", "Ö");\r
+      token = token.replaceAll("Ue", "Ü");\r
+      return token;   \r
     }\r
   };\r
-\r
-  // ----------------------------------------------------------------\r
-\r
-  private static final Map<String, Language> symbolToLangauge = new LinkedHashMap<String, Language>();\r
-\r
+  \r
   static {\r
-    symbolToLangauge.put(EN.symbol, EN);\r
-    symbolToLangauge.put(DE.symbol, DE);\r
+    for (final String lang : Locale.getISOLanguages()) {\r
+      if (lookup(lang) == null) {\r
+        new Language(new Locale(lang));\r
+      }\r
+    }\r
   }\r
 \r
+  // ----------------------------------------------------------------\r
+\r
   static Language lookup(final String symbol) {\r
-    return symbolToLangauge.get(symbol);\r
+    return symbolToLangauge.get(symbol.toLowerCase());\r
   }\r
 \r
 }\r