Version 62.1 by Ray Kiddy on 2023/11/13 11:57

Hide last authors
Pascal Robert 4.1 1 == Unicode ==
smmccraw 1.1 2
Ray Kiddy 62.1 3 See also: [[doc:documentation.Home.Development Architecture.Localization.UTF-8 Encoding Tips.WebHome]]
Pascal Robert 46.1 4
smmccraw 1.1 5 To Enable Unicode for your WO app, add the following to your application constructor:
6
Quinton Dolan 3.1 7 {{code}}
8 WOMessage.setDefaultEncoding("UTF8");
smmccraw 1.1 9
Quinton Dolan 3.1 10 {{/code}}
smmccraw 1.1 11
12 This tells all WOResponse and WORequest to use UTF8 (Unicode).
13
14 Then you just need to tell the browser. Make all your .wo pages include this meta tag in their HTML:
15
Pascal Robert 58.1 16 {{code 0="xml"}}
Quinton Dolan 3.1 17 <html>
18 <head>
19 <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
20 <!-- etc... -->
smmccraw 1.1 21
Quinton Dolan 3.1 22 {{/code}}
smmccraw 1.1 23
Pascal Robert 4.1 24 === Jesse Barnum ===
smmccraw 1.1 25
26 Great tip - here is a simple method call you can stick in your Application object to automatically achieve the results outlined above:
27
Quinton Dolan 3.1 28 {{code}}
29 private boolean enableUTFEncoding = false;
30
31 public void enableUTFEncoding() {
32 enableUTFEncoding = true;
33 WOMessage.setDefaultEncoding(_NSUtilities.UTF8StringEncoding);
34 }
35
36 public WOResponse dispatchRequest(WORequest theRequest) {
37 WOResponse result = super.dispatchRequest(theRequest);
38 if( enableUTFEncoding && "text/html".equals(result.headerForKey("content-type")) ) {
Pascal Robert 4.1 39 result.setHeader("text/html; charset=UTF-8; encoding=UTF-8", "content-type");
smmccraw 1.1 40 }
Quinton Dolan 3.1 41 return result;
42 }
smmccraw 1.1 43
Quinton Dolan 3.1 44 {{/code}}
smmccraw 1.1 45
Pascal Robert 4.1 46 === Helmut Schottmüller ===
smmccraw 1.1 47
48 Unfortunately it's not so easy if you want to use file upload fields and UTF-8 encoding in the same form. Adding a file upload component means that you have to set the form's enctype to "multipart/form-data". To force a multipart form to use UTF-8 encoding usually needs an enctype of "multipart/form-data; charset=UTF-8" but WO is not able to identify such a form as multipart form. You will get a "java.lang.IllegalArgumentException: This form is missing a 'enctype=multipart/form-data' attribute. It is required for WOFileUpload to work." error when you open the form in the browser.
49
50 To make sure that UTF-8 is supported in multipart forms as well, you have to add the following code to your Application object:
51
Quinton Dolan 3.1 52 {{code}}
Pascal Robert 4.1 53 public WORequest createRequest(String aMethod, String aURL, String anHTTPVersion,
Quinton Dolan 3.1 54 NSDictionary someHeaders, NSData aContent, NSDictionary someInfo) {
Pascal Robert 4.1 55 WORequest newRequest = super.createRequest(aMethod, aURL, anHTTPVersion,
Quinton Dolan 3.1 56 someHeaders, aContent, someInfo);
57 newRequest.setDefaultFormValueEncoding(_NSUtilities.UTF8StringEncoding);
58 return newRequest;
59 }
smmccraw 1.1 60
Quinton Dolan 3.1 61 {{/code}}
smmccraw 1.1 62
Pascal Robert 58.1 63 To make WOFileUpload components working I also had to add the launch parameter -WOUseLegacyMultipartParser true to my application. This launch parameter forces the parsing of all form values, the first time WORequest.formValues is called. See the [[apple developer documentation>>url:http://wocommunity.org/documents/javadoc/WebObjects/5.4.2/com/webobjects/appserver/WORequest.html||shape="rect"]] for additional information. Without -WOUseLegacyMultipartParser true I had serious problems in my applications using a WOFileUpload component because the bindings //data// and //filePath// have been emptied after a form POST.
smmccraw 1.1 64
65 With Jesse's code and this extension, you will be able to handle UTF-8 character data correctly in your WO application.
66
Johan Henselmans 61.2 67 If you use localized strings in your UTF-8 application you may also check out Project Wonder's [[ERXLocalizer>>doc:documentation.WOnder-ERXLocalizer]] class.
Ramsey Gurley 42.1 68
David Holt 56.1 69 === Project Localization tips ===
Ramsey Gurley 42.1 70
71 The following are some tips and suggestions for localizing a project in WOLips using Project Wonder.
72
73 ===== Eclipse Default Encoding =====
74
Pascal Robert 58.1 75 I prefer to keep my entire project in UTF-8 format for consistency. You can set that in your Eclipse General->Workspace preferences. The exception, of course will be your Localizable.strings files. Those have to be in UTF-16 format. I generally get warnings about the WOO file for my initial Main component whenever I create a new project, but if you right-click your Main.wo you'll see "Properties" at the very bottom of the contextual menu. Open that and flip your encoding between project default and UTF-8, save it, then open it back up and return it to the project default and the problem should go away. This is also how you set your Localized.strings file to UTF-16 even if the rest of your project is not UTF-16.
Ramsey Gurley 42.1 76
77 ===== Properties file =====
78
Pascal Robert 58.1 79 Let's say your project will be available in English and Japanese. You'll want to include the following in your Project->Resources->Properties file:
Ramsey Gurley 42.1 80
81 {{noformat}}
82 # Localization
83 er.extensions.ERXLocalizer.defaultLanguage=English
84 er.extensions.ERXLocalizer.fileNamesToWatch=("Localizable.strings","ValidationTemplate.strings")
85 er.extensions.ERXLocalizer.availableLanguages=(English,Japanese)
86 er.extensions.ERXLocalizer.frameworkSearchPath=(app,ERDirectToWeb,ERExtensions)
87
88 # Project Encoding
89 er.extensions.ERXApplication.DefaultEncoding=UTF-8
90
91 {{/noformat}}
92
Pascal Robert 46.1 93 Note that if you need to customize the locale for a language, such as Canadian French, you can do so with this property:
94
95 {{noformat}}
96 er.extensions.ERXLocalizer.French_CA.locale = fr_ca
97
98 {{/noformat}}
99
Pascal Robert 58.1 100 (% style="color: rgb(51,51,51);" %)The other changes are then in the er.extensions.ERXLocalizer.availableLanguages and ERXLanguages:(%%)
101 (% style="color: rgb(51,51,51);" %)In the above case after adding canadian french these would change in:
David Holt 56.1 102
Pascal Robert 46.1 103 {{noformat}}
104 er.extensions.ERXLocalizer.availableLanguages=(English,Japanese,French_CA)
105
106 {{/noformat}}
107
Pascal Robert 58.1 108 (% style="color: rgb(51,51,51);" %)Localized formatters use this property:
David Holt 56.1 109
110 {{noformat}}
111 er.extensions.ERXLocalizer.useLocalizedFormatters=false
112
113 {{/noformat}}
114
Ramsey Gurley 42.1 115 ===== Localized strings and components =====
116
Pascal Robert 58.1 117 For each language available, you will need a corresponding Localizable.strings file. This file should be located in Projects->Resources->"Lang".lproj directory. In these directories, you'll store localized resources such as Localizable.strings files and localized components. So, continuing with the above example, you should create two new Localizable.strings files in the following places in your project directory:
Ramsey Gurley 42.1 118
Pascal Robert 58.1 119 >Project->Resources->English.lproj->Localizable.strings
120 > Project->Resources->Japanese.lproj->Localizable.strings
121 > Project->Resources->French_CA.lproj->Localizable.strings
Ramsey Gurley 42.1 122
Pascal Robert 58.1 123 As mentioned earlier, it's recommended that these be in UTF-16 format. You can do that by right clicking on the file in WOLips and selecting "Properties." In the resources panel, change from the project default encoding to UTF-16.
Ramsey Gurley 42.1 124
Pascal Robert 58.1 125 If you have any components that need localizing, then you should relocate that component from your Project->Components folder into the appropriate Lang.lproj folder. Then make a copy of the component into the remaining lproj directories and you can begin the process of localizing the component. You do not need more than one copy of the associated API or java file. You only need duplicates of the WO. So, as an example, if you wanted to localize
Ramsey Gurley 42.1 126
Pascal Robert 58.1 127 >Project->Components->Main WO
Ramsey Gurley 42.1 128
Pascal Robert 58.1 129 You would right-click->Refactor->Move it to
Ramsey Gurley 42.1 130
Pascal Robert 58.1 131 >Project->Resources->English.lproj->Main WO
132
133 and then right-click->Copy it from English.lproj and right-click->Paste it into Japanese.lproj. At this point, when you open the component in WOLips, there will be a tab at the bottom of the component editor view that allows you to switch back and forth between different localized versions of that component.
134
Pascal Robert 46.1 135 Your layout would end up something like this:
Ramsey Gurley 42.1 136
Pascal Robert 58.1 137 [[image:attach:ERXLocalizerEclipseLayout.png]]
Ramsey Gurley 42.1 138
Pascal Robert 46.1 139 ===== Localized EOAttributes =====
Ramsey Gurley 42.1 140
Pascal Robert 58.1 141 In Wonder, it is also possible to localize attributes. Let's say we have an entity //Blog// with an attribute //content// that we want to localize. This will be realized by not creating a column //content// in the database but a column for each specified language we want i.e. //content_en//, //content_fr//, ...
Ramsey Gurley 42.1 142
David Holt 56.1 143 To tell EOF that we want a specific attribute localized you have to add a key ERXLanguages to its user info.
Ramsey Gurley 42.1 144
Pascal Robert 58.1 145 [[image:attach:ERXLocalizerUserInfo_correct.png]]
David Holt 56.1 146
147 In this example we set the type to //Array// and add an item for each needed language setting its value to the language code. This must be done for each attribute in our model we want to localize. If you have many localized attributes that have the very same list of languages and you will likely be changing that list in the future you can define your language list either for a whole model or for all models instead. The first way to specify a per model language list is to put an ERXLanguages key into the user info of the model. For a global setting put that key into your property file:
148
Pascal Robert 46.1 149 {{noformat}}
150 ERXLanguages = (en,jp,fr_ca)
Ramsey Gurley 42.1 151
Pascal Robert 46.1 152 {{/noformat}}
Ramsey Gurley 42.1 153
Pascal Robert 58.1 154 All attributes that should use those global settings must have a key //ERXLanguages// in their user info with a type **different** to //Array//. Its value can be anything as only the presence of the key is of importance. The order that the languages are applied to an attribute is:
Ramsey Gurley 42.1 155
David Holt 56.1 156 * attribute user info with an array for ERXLanguages
157 * if type of found user info is not an array then get array from key ERXLanguages from user info of the model
158 * if user info of the model has no key ERXLanguages look for a property ERXLanguages in your property files
159 * if no property ERXLanguages is found ignore localization
Ramsey Gurley 42.1 160
161 ===== Direct Actions =====
162
Pascal Robert 58.1 163 If you are defaulting to direct actions, you may not have a session. If you do not have a session, the server will return the default language specified in the Properties mentioned above. If you're using direct actions and you don't like that behavior, you can stick this in your direct action class:
Ramsey Gurley 42.1 164
165 {{code}}
David Holt 56.1 166 @Override
Ramsey Gurley 42.1 167 public WOActionResults performActionNamed(String actionName) {
168 if(!context().hasSession()) {
169 ERXLocalizer localizer =
170 ERXLocalizer.localizerForLanguages(context().request().browserLanguages());
171 ERXLocalizer.setCurrentLocalizer(localizer);
172 }
173 return super.performActionNamed(actionName);
174 }
175
176 {{/code}}
177
David Holt 56.1 178 That should give the user their browser's default language setting instead of your server's default language setting until a session is created.
Ramsey Gurley 42.1 179
Pascal Robert 58.1 180 [[attach:WO.Development-Localization and Internationalization@LocalizerTest.zip]] is an example application demonstrating the sessionless use of the localizer with localized strings and localized components, storing the language state in a cookie.
Pascal Robert 46.1 181
Ramsey Gurley 42.1 182 ===== Database setup =====
183
Pascal Robert 58.1 184 Outside of this, if you are using a database, you'll need to make sure that is encoded properly as well. I'm using MySQL, so I have in my EOModel:
Ramsey Gurley 42.1 185
186 jdbc:mysql:~/~/localhost/mydatabase?capitalizeTypenames=true&zeroDateTimeBehavior=convertToNull&characterEncoding=UTF-8
187
Pascal Robert 58.1 188 The database itself is set to default to "UTF8" encoding. (No hyphen in UTF8 for MySQL) You can set that in the "Options" pane of MySQL Administrator.app under the "Advanced" popup menu item in the "Def. char set" field. Of course, you'll need to use the correct database types too, meaning don't use a blob for text storage. Use varchar and longtext (varcharLarge is the name of the Wonder prototype) instead.
David Holt 56.1 189
190 ===== Localization presentation from WOWODC West 2009 =====
191
Johan Henselmans 59.1 192 Guido Neitzer did a localization presentation at WOWODC West 2009 that give a good overview of how to localize your apps. The presentation is available [[here>>url:http://www.wocommunity.org/podcasts/wowodc/west09/WOWODC09W-Localization.mov||shape="rect"]].
David Holt 56.1 193
Pascal Robert 58.1 194