Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

Initial commit

  • Loading branch information...
commit 7c3e13272efbd19f468f551d7f8d93cbad581893 0 parents
@4e6 authored
8 bin/alh.sh
@@ -0,0 +1,8 @@
+#!/bin/sh
+#
+# Start-up script
+
+L10N_HELPER_HOME=`dirname "$0"`
+L10N_HELPER_HOME=`dirname "$L10N_HELPER_HOME"`
+
+java -jar $L10N_HELPER_HOME/lib/l10n-helper.jar $1
1  build/MANIFEST.MF
@@ -0,0 +1 @@
+Main-Class: the4e6.AndroidTranslationsHelper
10 build/build.sh
@@ -0,0 +1,10 @@
+#!/bin/sh
+#
+# Build script. Run from build directory.
+
+cd ../bin
+
+jar -cvmf ../build/MANIFEST.MF ../lib/helper.jar *
+cd ../build
+java -jar ../lib/proguard.jar @proguard.cfg -verbose
+rm ../lib/helper.jar
42 build/proguard.cfg
@@ -0,0 +1,42 @@
+-injars ../lib/helper.jar
+-injars ../lib/scala-library.jar
+-outjars ../lib/l10n-helper.jar
+-libraryjars ../lib/rt.jar
+
+-dontwarn **$$anonfun$*
+-dontwarn scala.collection.immutable.RedBlack$Empty
+-dontwarn scala.tools.**,plugintemplate.**
+
+-keepclasseswithmembers public class * {
+ public static void main(java.lang.String[]);
+}
+
+-keep class * implements org.xml.sax.EntityResolver
+
+-keepclassmembers class * {
+ ** MODULE$;
+}
+
+-keepclassmembernames class scala.concurrent.forkjoin.ForkJoinPool {
+ long eventCount;
+ int workerCounts;
+ int runControl;
+ scala.concurrent.forkjoin.ForkJoinPool$WaitQueueNode syncStack;
+ scala.concurrent.forkjoin.ForkJoinPool$WaitQueueNode spareStack;
+}
+
+-keepclassmembernames class scala.concurrent.forkjoin.ForkJoinWorkerThread {
+ int base;
+ int sp;
+ int runState;
+}
+
+-keepclassmembernames class scala.concurrent.forkjoin.ForkJoinTask {
+ int status;
+}
+
+-keepclassmembernames class scala.concurrent.forkjoin.LinkedTransferQueue {
+ scala.concurrent.forkjoin.LinkedTransferQueue$PaddedAtomicReference head;
+ scala.concurrent.forkjoin.LinkedTransferQueue$PaddedAtomicReference tail;
+ scala.concurrent.forkjoin.LinkedTransferQueue$PaddedAtomicReference cleanMe;
+}
BIN  lib/l10n-helper.jar
Binary file not shown
100 src/the4e6/AndroidTranslationsHelper.scala
@@ -0,0 +1,100 @@
+package the4e6
+
+import java.io.File
+import scala.xml._
+
+/** Helps to find missing or obsolete translations of localized resources
+ * in android project. */
+object AndroidTranslationsHelper {
+ def main(args: Array[String]) {
+ if (args.isEmpty) {
+ exit(helpMsg)
+ }
+
+ /** Android project root folder. */
+ val project = new File(args(0))
+ if (!project.exists) {
+ exit("folder not exists")
+ }
+
+ /** Try to find original strings.xml file in 'values' folder. */
+ val stringsOrig = findStrings(project, "values$")
+ if (stringsOrig.isEmpty) {
+ exit("res/values/strings.xml not found")
+ }
+
+ /** Try to find localized strings.xml file in 'values*' folders. */
+ val stringsLocalized =
+ findStrings(project, "values.") sortWith { _.getParent < _.getParent }
+ if (stringsLocalized.isEmpty) {
+ exit("localized resources not found")
+ }
+
+ /** Original XML resources from values/strings.xml */
+ val rOrig: NodeSeq = XML.loadFile(stringsOrig.head) \\ "resources"
+
+ stringsLocalized.foreach(f => {
+ val r = XML.loadFile(f) \\ "resources"
+ printNiceName(f)
+ val extraLine_? =
+ resTypes.map(t => {
+ val names = mkNamesSet(r, t)
+ val namesOrig = mkNamesSet(rOrig, t)
+ printDiffs(t, namesOrig diff names, names diff namesOrig)
+ }) contains true
+ if (extraLine_?) println
+ })
+ }
+
+ /** Returns array of all string.xml files according to
+ * 'dir'/res/'regex'/strings.xml pattern. */
+ def findStrings(dir: File, regex: String): Array[File] =
+ dir.listFiles
+ .withFilter { _.getName == "res" }
+ .flatMap { _.listFiles.filter(f => regex.r.findFirstIn(f.getName).isDefined) }
+ .flatMap { _.listFiles.filter(_.getName == "strings.xml") }
+
+ /** Returns a set of resource names. */
+ def mkNamesSet(ns: NodeSeq, tag: String): Set[String] =
+ (ns \ tag) map { _ \ "@name" text } toSet
+
+ def printNiceName(f: File) {
+ println(f.getParentFile.getName + "/" + f.getName)
+ }
+
+ /**
+ * Print diff section for given resource type.
+ *
+ * @return flag, if there is a need for extra blank line after output */
+ def printDiffs(resType: String, t: Set[String], o: Set[String]): Boolean = {
+ if (t.nonEmpty || o.nonEmpty) {
+ println(" " + resType)
+ t map { " [T] " + _ } foreach println
+ o map { " [O] " + _ } foreach println
+ true
+ } else false
+ }
+
+ def exit(msg: String) {
+ println(msg)
+ System.exit(0)
+ }
+
+ /** List of android resource types. */
+ val resTypes = "string" :: "string-array" :: "plurals" :: Nil
+
+ val helpMsg =
+ "Helps to find missing or obsolete translations for android resources\n" +
+ "\n" +
+ "Usage: You must specify android project folder\n" +
+ "`alh.sh /path/to/android/project'\n" +
+ "\n" +
+ "Output:\n" +
+ "[filename]\n" +
+ " *[resource type]\n" +
+ " *[T] [resource name]\n" +
+ " *[O] [resource name]\n" +
+ "\n" +
+ "[T] Resources need to be translated (exists in original xml but not in localized version)\n" +
+ "[O] Obsolete resources (exists in localized version but not in original one)\n"
+}
Please sign in to comment.
Something went wrong with that request. Please try again.