- Timestamp:
- 2022-01-13T12:57:05+13:00 (2 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
main/trunk/greenstone3/src/java/org/greenstone/gsdl3/util/XSLTUtil.java
r35745 r35996 822 822 } 823 823 824 public static String getInterfaceStringsAsJavascript(String interface _name, String lang, String prefix)824 public static String getInterfaceStringsAsJavascript(String interfaceName, String lang, String prefix) 825 825 { 826 826 String prependToPrefix = "gs.text"; 827 return XSLTUtil.getInterfaceStringsAsJavascript(interface _name, lang, prefix, prependToPrefix);827 return XSLTUtil.getInterfaceStringsAsJavascript(interfaceName, lang, prefix, prependToPrefix); 828 828 } 829 829 830 830 /** 831 * Generates a Javascript object graph to store language strings. Leaf nodes contain the string and the previous node, the key.832 * Further preceding nodes denote the prefix of the string (i.e. the gs3 language strings object, which interface they belong to etc.).833 * Accessing a language string on a well-formed JS object graph will be similar to this: const myString = gs.text.atea.asr.Title;834 * @param interface _name The name of the interface to retrieve language strings for.831 * Generates a Javascript object graph to store language strings. Leaf nodes are the key, and their value the string. 832 * Further preceding nodes denote the prefix of the string within the language strings property file. 833 * Accessing a language string from the object graph can be done as such: 'const myString = {prependToPrefix}.{prefix}.{key};' 834 * @param interfaceName The name of the interface to retrieve language strings for. 835 835 * @param lang The language to retrieve. 836 * @param prefix The prefix to place the language strings under (e.g. atea.asr).837 * @param prependToPrefix 838 * @return Javascript code that will generate the language string object graph.836 * @param prefix The prefix to to retrieve strings under. E.g. a value of 'atea.macroniser' will only retrieve strings prefixed with that value. 837 * @param prependToPrefix An accessor string to prepend to the generated JS object graph. 838 * @return Stringified Javascript code that will generate the language string object graph. 839 839 */ 840 public static String getInterfaceStringsAsJavascript(String interface _name, String lang, String prefix, String prependToPrefix)840 public static String getInterfaceStringsAsJavascript(String interfaceName, String lang, String prefix, String prependToPrefix) 841 841 { 842 842 // now we allow looking for files in the interface's resources folder 843 CustomClassLoader my_loader = new CustomClassLoader(XSLTUtil.class.getClassLoader(), 844 GSFile.interfaceResourceDir(GlobalProperties.getGSDL3Home(), interface_name)); 845 String prefixwithdot = prefix + "."; 843 CustomClassLoader my_loader = new CustomClassLoader( 844 XSLTUtil.class.getClassLoader(), 845 GSFile.interfaceResourceDir(GlobalProperties.getGSDL3Home(), interfaceName) 846 ); 846 847 847 848 StringBuffer outputStr = new StringBuffer(); 848 HashSet<String> initialisedDepths = new HashSet<>(); 849 850 // Initialise the root prefix object 851 outputStr.append("if(!" + prependToPrefix + ") { "); 852 outputStr.append(prependToPrefix + " = {}; "); 853 outputStr.append("}\n"); 854 initialisedDepths.add(prependToPrefix); 855 856 // Initialise the prefix object structure, handling '.' characters. 857 // JS identifies these as property accessors, hence requiring a new object for each 'level'. 858 String currentDepth = prependToPrefix; 859 String[] prefixComponents = prefix.split("\\."); 860 861 for (String element : prefixComponents) { 862 currentDepth += "." + element; 863 864 outputStr.append("if(!" + currentDepth + ") { "); 865 outputStr.append(currentDepth + " = {}; "); 866 outputStr.append("}\n"); 867 868 initialisedDepths.add(currentDepth); 869 } 870 871 for (String dictName : new String[] { "interface_" + interface_name, "interface_default", 872 "interface_default2" }) { 873 // get all the keys from the english dictionary as this is a complete set 849 HashSet<String> initialisedNodes = new HashSet<>(); 850 851 // The dictionaries to pull keys from 852 String[] dictionaries = new String[] { 853 "interface_" + interfaceName, 854 "interface_default", 855 "interface_default2" 856 }; 857 858 for (String dictName : dictionaries) 859 { 860 // get all the *keys* from the english dictionary as this is a complete set 874 861 Dictionary dict = new Dictionary(dictName, "en", my_loader); 875 Enumeration keys = dict.getKeys();862 Enumeration<String> keys = dict.getKeys(); 876 863 if (keys == null) { 877 864 continue; … … 880 867 // Get all properties in the language-specific dictionary with the given key prefix 881 868 // Create Javascript strings of the form: 882 // prefixPath.key= "value";\n 883 while (keys.hasMoreElements()) { 884 String key = (String) keys.nextElement(); 885 if (key.startsWith(prefixwithdot)) { 886 String[] keyComponents = key.split("\\."); 887 currentDepth = prependToPrefix + "." + prefix; 888 889 for (int i = prefixComponents.length; i < keyComponents.length - 1; i++) { 890 currentDepth += "." + keyComponents[i]; 891 892 if (initialisedDepths.contains(currentDepth)) { 893 continue; 894 } 895 896 outputStr.append("if(!" + currentDepth + ") { "); 897 outputStr.append(currentDepth + " = {}; "); 898 outputStr.append("}\n"); 899 900 initialisedDepths.add(currentDepth); 901 } 869 // prependToPrefix.key="value";\n 870 while (keys.hasMoreElements()) 871 { 872 String key = keys.nextElement(); 873 if (key.startsWith(prefix)) 874 { 875 // Builds the JS object structure we need to access the key. 876 // Also has the side effect of ensuring that any '.' characters in 877 // the key are valid once parsed by the JS engine. 878 buildJSObjectGraph( 879 outputStr, 880 prependToPrefix + "." + key.substring(0, key.lastIndexOf(".")), // Strip the actual key from the path 881 initialisedNodes 882 ); 902 883 903 884 // get the language dependent value for the key. This will return the english if no value found for the given lang 904 String value = getInterfaceText(interface_name, dictName, lang, key, null); 905 906 outputStr.append(prependToPrefix); 907 outputStr.append("."); 908 outputStr.append(key); 909 outputStr.append("=\""); 910 outputStr.append(value); 911 outputStr.append("\";\n"); 885 String value = getInterfaceText(interfaceName, dictName, lang, key, null); 886 outputStr.append(prependToPrefix + "." + key + "=\"" + value + "\";\n"); 912 887 } 913 888 } … … 915 890 916 891 return outputStr.toString(); 892 } 893 894 /** 895 * Builds a string that will initialize an empty javascript object. 896 * I.e. 'gs.text??={};'. 897 * @param buffer The buffer to append the string to. 898 * @param objectPath The path to the JS object to initialize. E.g. gs.text.atea. 899 * @param isRootObject A value indicating whether the object is a root object. If not, a logical nullish assignment statement will be built in order to produce cleaner javascript. 900 */ 901 private static void buildJSObjectInitializer( 902 StringBuffer buffer, 903 String objectPath, 904 Boolean isRootObject 905 ) 906 { 907 if (!isRootObject) { 908 buffer.append(objectPath + "??={};\n"); 909 return; 910 } 911 912 buffer.append("if(typeof " + objectPath + "===\"undefined\"){" + objectPath + "={};}\n"); 913 } 914 915 /** 916 * Builds a string that will initialize a javascript object graph. 917 * I.e. the structure required to access the final property on the object graph 'gs.text.atea.asr'. 918 * @param buffer The buffer to append the string to. 919 * @param objectGraph The object graph to build. 920 * @param visitedNodes A map of previously built nodes. Updated to add nodes that are produced in this function. 921 */ 922 private static void buildJSObjectGraph( 923 StringBuffer buffer, 924 String objectGraph, 925 HashSet<String> preBuiltNodes 926 ) 927 { 928 if (objectGraph == null) { 929 return; 930 } 931 932 String[] nodes = objectGraph.split("\\."); 933 934 if (!preBuiltNodes.contains(nodes[0])) { 935 buildJSObjectInitializer(buffer, nodes[0], true); 936 preBuiltNodes.add(nodes[0]); 937 } 938 939 if (nodes.length == 1) { 940 return; 941 } 942 943 String currentDepth = nodes[0]; 944 for (int i = 1; i < nodes.length; i++) { 945 currentDepth += "." + nodes[i]; 946 if (preBuiltNodes.contains(currentDepth)) { 947 continue; 948 } 949 950 buildJSObjectInitializer(buffer, currentDepth, false); 951 preBuiltNodes.add(currentDepth); 952 } 917 953 } 918 954
Note:
See TracChangeset
for help on using the changeset viewer.