Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

Sencha Touch 2 PR3 version.

  • Loading branch information...
commit 9b6cfe9b32b4f4cd383f7ecb7ab2e34a9c0dfde1 1 parent 536de2c
@elmasse authored
View
52 README
@@ -1,8 +1,50 @@
-Ext.i18n.Bundle
+# Ext.i18n.Bundle
-version: 0.2.2
+##v0.3
-This version is the first working draft for Sencha Touch 1.1.
+Ext.i18n.Bundle allows to use properties files (or bundle files) from Java to use them as i18n resources with Sencha Touch.
-I'm currently working on documentation. By now you can visit my home page (http://elmasse.gaver.nl) and check there How Bundle extension work.
-The Bundle API has no changes so you can use it as you were doing before.
+### Example
+
+ Ext.application({
+ name: 'AppTest',
+ launch: function(){
+ //1
+ bundle = Ext.create('Ext.i18n.Bundle',{
+ bundle: 'Application',
+ lang: 'es-ES',
+ path: 'resources',
+ noCache: false
+ });
+ //2
+ bundle.onReady(function(){
+ Ext.create('Ext.Panel',{
+ fullscreen: true,
+ html: bundle.getMsg('panel.html') //3
+ });
+ });
+ }
+ });
+
+Using Ext.i18n.Bundle is very simple. You just need to create your bundle instance (1). In this case we want to retrieve a bundle file called Application for Spanish language - es-ES - located at resources path. This will load a file called Application_es-ES.properties:
+
+GET http://yourdomain/resources/Application_es-ES.properties
+
+In case this file doesn't exist, then the bundle will try at:
+
+GET http://yourdomain/resources/Application.properties
+
+for the default bundle file.
+
+You need to call your code once your bundle file is loaded, so you need to place your code inside onReady method (2). Finally, to access a bundle key, use getMsg method passing the key as argument. That function will retrieve the content for the given key or a String with key name followed by .undefined so you can track what is not actually defined in your bundle file.
+
+##Release Notes
+
+###v0.3
+* Sencha Touch 2 PR3 comaptible code.
+* Removed config method. All the requests are made using GET method.
+* Solved issue with extra arguments passed to URL. Now you have no limits, start nor group extra parameters in URL.
+
+###Known issues
+* PhoneGap is using XHR thru file:// protocol then AjaxProxy doesn't retrieve data. Note: This was solved in previous version for Sencha Touch 1 overriding AjaxProxy createRequestCallback method (v0.2.2) see js/AjaxLocalProxy.js
+
View
19 demo/demo.js
@@ -0,0 +1,19 @@
+Ext.application({
+ name: 'AppTest',
+ launch: function(){
+
+ bundle = Ext.create('Ext.i18n.Bundle',{
+ bundle: 'Application',
+ lang: 'es-ES',
+ path: 'resources',
+ noCache: true
+ });
+
+ bundle.onReady(function(){
+ Ext.create('Ext.Panel',{
+ fullscreen: true,
+ html: bundle.getMsg('panel.html')
+ });
+ });
+ }
+});
View
185 i18n/Bundle.js
@@ -0,0 +1,185 @@
+/**
+ * @author Maximiliano Fierr
+ * @class Ext.i18n.Bundle
+ * @extends Ext.data.Store
+ *
+ * Bundle is used to load .properties bundle files based in language and expose the bundle's keys thru getMsg method.
+ <code>
+Ext.application({
+ name: 'AppTest',
+ launch: function(){
+
+ bundle = Ext.create('Ext.i18n.Bundle',{
+ bundle: 'Application',
+ lang: 'es-ES',
+ path: 'resources',
+ noCache: false
+ });
+
+ bundle.onReady(function(){
+ Ext.create('Ext.Panel',{
+ fullscreen: true,
+ html: bundle.getMsg('panel.html')
+ });
+ });
+ }
+});
+
+ </code>
+ */
+Ext.define('Ext.i18n.Bundle', {
+ extend: 'Ext.data.Store',
+ requires: [
+ 'Ext.i18n.reader.Property',
+ 'Ext.i18n.model.Property'
+ ],
+
+ //@private
+ defaultLanguage: 'en-US',
+ //@private
+ resourceExt: '.properties',
+
+ config:{
+ /**
+ * @cfg bundle {String} bundle name for properties file. Default to message
+ */
+ bundle: 'message',
+
+ /**
+ * @cfg path {String} URI to properties files. Default to resources
+ */
+ path: 'resources'
+
+ /**
+ * @cfg lang {String} Language in the form xx-YY where:
+ * xx: Language code (2 characters lowercase)
+ * YY: Country code (2 characters upercase).
+ * Optional. Default to browser's language. If it cannot be determined default to en-US.
+ */
+
+ /**
+ * @cfg noCache {boolean} whether or not to disable Proxy's cache. Optional. Defaults to true.
+ */
+
+ },
+
+
+ constructor: function(config){
+ config = config || {};
+
+ var me = this,
+ language = me.formatLanguageCode(config.lang || me.guessLanguage()),
+ noCache = (config.noCache !== false),
+ url;
+
+ me.language = language;
+ me.bundle = config.bundle || me.bundle;
+ me.path = config.path || me.path;
+
+ url = this.buildURL(language);
+
+ delete config.lang;
+ delete config.noCache;
+
+ Ext.applyIf(config, {
+ autoLoad: true,
+ model: 'Ext.i18n.model.Property',
+ proxy:{
+ type: 'ajax',
+ url: url,
+ noCache: noCache,
+ reader: {
+ type: 'property'
+ },
+ //avoid sending limit, start & group params to server
+ getParams: Ext.emptyFn
+ },
+ listeners:{
+ 'load': this.onBundleLoad,
+ scope: this
+ }
+ });
+
+ me.callParent([config]);
+ me.proxy.on('exception', this.loadParent, this, {single: true});
+ },
+
+ /**
+ * @private
+ */
+ guessLanguage: function(){
+ return (navigator.language || navigator.browserLanguage
+ || navigator.userLanguage || this.defaultLanguage);
+ },
+
+ /**
+ * @method: getMsg
+ * Returns the content associated with the bundle key or {bundle key}.undefined if it is not specified.
+ * @param: key {String} Bundle key.
+ * @return: {String} The bundle key content.
+ */
+ getMsg: function(key){
+ return this.getById(key)? Ext.util.Format.htmlDecode(this.getById(key).get('value')) : key + '.undefined';
+ },
+
+ /**
+ * @method: onReady
+ * The fn will be called when the Bundle file is loaded.
+ * @param: fn {Function}
+ */
+ onReady: function(fn){
+ this.readyFn = fn;
+ this.on('loaded', this.readyFn, this);
+ },
+
+ /**
+ * @private
+ */
+ onBundleLoad: function(store, record, success, op) {
+ if(success){
+ this.fireEvent('loaded');
+ }
+ },
+
+ /**
+ * @private
+ */
+ onProxyLoad: function(op){
+ if(op.getRecords()){
+ this.callParent(arguments);
+ }
+ },
+
+ /**
+ * @private
+ */
+ buildURL: function(language){
+ var url = '';
+ if (this.path) url+= this.path + '/';
+ url+=this.bundle;
+ if (language) url+= '_'+language;
+ url+=this.resourceExt;
+ return url;
+ },
+
+ /**
+ * @private
+ */
+ loadParent: function(){
+ this.proxy.url = this.buildURL();
+ this.load();
+ },
+
+ /**
+ * @private
+ */
+ formatLanguageCode: function(lang){
+ var langCodes = lang.split('-');
+ langCodes[0] = (langCodes[0]) ? langCodes[0].toLowerCase() : '';
+ langCodes[1] = (langCodes[1]) ? langCodes[1].toUpperCase() : '';
+ return langCodes.join('-');
+ }
+
+
+
+});
View
7 i18n/model/Property.js
@@ -0,0 +1,7 @@
+Ext.define('Ext.i18n.model.Property', {
+ extend: 'Ext.data.Model',
+
+ idProperty: 'key',
+ fields: ['key', 'value']
+
+});
View
66 i18n/reader/Property.js
@@ -0,0 +1,66 @@
+Ext.define('Ext.i18n.reader.Property', {
+ extend: 'Ext.data.reader.Reader',
+ alias : 'reader.property',
+
+ constructor: function(config){
+ config = config || {};
+
+ Ext.applyIf(config, {
+ idProperty: 'id',
+ successProperty: 'success',
+ totalProperty: 'total'
+ });
+
+ this.callParent([config]);
+ },
+
+ read: function(response){
+ var propertyFile = response.responseText;
+ if(!propertyFile)
+ throw {message: "PropertyReader.read: File not found"};
+
+ return this.readRecords(propertyFile);
+ },
+
+ readRecords: function(propertyFile){
+ var Record = this.recordType,
+ Model = this.model,
+ records = [], record, kv,
+ f = this.readLines(propertyFile),
+ l = f.length;
+
+ for(var i = 0; i < l; i++){
+ var kl = f[i].search(/[\s:=]/);
+ record = new Model({
+ value : this.clearValueExtraChars(f[i].substring(kl+1)),
+ key : this.clearKeyExtraChars(f[i].substring(0, kl))
+ });
+
+ records[i] = record;
+ }
+
+ return Ext.create('Ext.data.ResultSet', {
+ total : records.length,
+ count : records.length,
+ records: records,
+ success: true
+ });
+ },
+
+ createAccessor: function(){},
+
+ clearKeyExtraChars: function(s){
+ return (s ? s.replace(/[:=]/gi, "") : "");
+ },
+
+ clearValueExtraChars: function(s){
+ return (s ? s.replace(/\\\s*\n/gi, "") : "");
+ },
+
+ //private
+ readLines: function(file){
+ return (file ? file.match(/.*(.*\\\s*\n)+.*|^((?!^\s*[#!]).).*$/gim) : []);
+ }
+
+
+});
View
30 index.html
@@ -1,20 +1,22 @@
<!DOCTYPE html>
<html>
<head>
- <meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
- <title>Ext.i18n.Bundle [Test] on Sencha Touch</title>
-
- <link rel="stylesheet" type="text/css" href="sencha/resources/css/sencha-touch.css" />
- <script type="text/javascript" src="sencha/sencha-touch-debug.js"></script>
-
- <!-- Uncomment next line if you plan to work on phonegap or load local files via xhr -->
- <!--
- <script type="text/javascript" src="js/AjaxLocalProxy.js" charset="utf-8"></script>
- -->
- <script type="text/javascript" src="js/PropertyReader.js"></script>
- <script type="text/javascript" src="js/Bundle.js"></script>
-
- <script type="text/javascript" src="js/test.js"></script>
+ <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+ <title>Ext.i18n.Bundle for Sencha Touch</title>
+ <meta name="author" content="Maximiliano Fierro">
+ <link rel="stylesheet" href="../common-libs/sencha-touch-2-pr3/resources/css/sencha-touch.css">
+ <script src="../common-libs/sencha-touch-2-pr3/sencha-touch-all-debug.js"></script>
+
+ <script>
+ Ext.Loader.setConfig({
+ enabled: true,
+ paths: {
+ 'Ext.i18n': 'i18n'
+ }
+ });
+ </script>
+
+ <script type="text/javascript" src="demo/demo.js"></script>
</head>
<body>
View
18 resources/Application_en-US.properties
@@ -0,0 +1,18 @@
+##
+# Testing Comments
+##
+
+!Another comment
+
+#separate keys with :
+panel.title:"quoted panel title"
+# or =
+panel.html=Something goes here! \
+Actually this text is part of panel.html key too!
+# or simple space
+back.button Go To {0}
+
+ # this is also a comment
+
+#In this case the space is used as separator, so : becomes part of the message!
+panel.some : <- this are part of the message
View
2  resources/Application_es-ES.properties
@@ -1,4 +1,4 @@
#panel.title 'titulo del panel'
panel.title "titulo del panel # sd"
-panel.html " Algo puede ir aca d'antoint \"no se\" "
+panel.html Algo puede ir aca d'antoint \"no se\"
Please sign in to comment.
Something went wrong with that request. Please try again.