Enhancing Worker Digital Experience: A Hands-on Workshop for Partners
international PHP2011_Kore Nordmann_Designing multilingual applications
1. Designing Multilingual Applications
International PHP Conference – Spring Edition
Kore Nordmann <kore@qafoo.com>
May 30, 2011
Designing Multilingual Applications 1 / 35
2. About me
Degree in computer sience
More than 10 years of Qafoo
passion for software quality
professional PHP
Open source enthusiasts
Contributing to various
FLOSS projects
Designing Multilingual Applications 2 / 35
3. About me
Degree in computer sience
More than 10 years of Qafoo
passion for software quality
professional PHP
Open source enthusiasts
Contributing to various
FLOSS projects
Designing Multilingual Applications 2 / 35
4. About me
Degree in computer sience
More than 10 years of Qafoo
passion for software quality
professional PHP
Open source enthusiasts
Contributing to various
FLOSS projects
Designing Multilingual Applications 2 / 35
5. About me
Co-founder of
Degree in computer sience
More than 10 years of Qafoo
passion for software quality
professional PHP
Open source enthusiasts
Contributing to various
FLOSS projects
Designing Multilingual Applications 2 / 35
6. About me
Co-founder of
Degree in computer sience
More than 10 years of Qafoo
passion for software quality
professional PHP
Open source enthusiasts We help people to create
Contributing to various high quality PHP
FLOSS projects applications.
Designing Multilingual Applications 2 / 35
7. About me
Co-founder of
Degree in computer sience
More than 10 years of Qafoo
passion for software quality
professional PHP
Open source enthusiasts We help people to create
Contributing to various high quality PHP
FLOSS projects applications.
http://qafoo.com
Designing Multilingual Applications 2 / 35
8. Motivation
Multilingual / Multicultural applications can be hard
Different types of applications:
Single fixed language
Consistent language per installation
Multilingual content
Designing Multilingual Applications 3 / 35
9. Motivation
Multilingual / Multicultural applications can be hard
Different types of applications:
Single fixed language
Consistent language per installation
Multilingual content
Designing Multilingual Applications 3 / 35
10. Motivation
Multilingual / Multicultural applications can be hard
Different types of applications:
Single fixed language
Consistent language per installation
Multilingual content
Designing Multilingual Applications 3 / 35
11. Motivation
Multilingual / Multicultural applications can be hard
Different types of applications:
Single fixed language
Consistent language per installation
Multilingual content
Designing Multilingual Applications 3 / 35
12. Where are the problems?
View Model
Dispatcher Controller
Designing Multilingual Applications 4 / 35
13. Outline
The Dispatcher
The Model
The View
Conclusion
Designing Multilingual Applications 5 / 35
14. Locate your user
Parsing accept headers is not hard
Possbile to do by regular expression
Never use geolocation for language selection
Or I’ll get back at you!
Result: de , en GB , cs CZ.UTF-8 , de AU@euro , . . .
Format: langauge[ territory][.codeset][@modifier]
Designing Multilingual Applications 6 / 35
15. Locate your user
Parsing accept headers is not hard
Possbile to do by regular expression
Never use geolocation for language selection
Or I’ll get back at you!
Result: de , en GB , cs CZ.UTF-8 , de AU@euro , . . .
Format: langauge[ territory][.codeset][@modifier]
Designing Multilingual Applications 6 / 35
16. Locate your user
Parsing accept headers is not hard
Possbile to do by regular expression
Never use geolocation for language selection
Or I’ll get back at you!
Result: de , en GB , cs CZ.UTF-8 , de AU@euro , . . .
Format: langauge[ territory][.codeset][@modifier]
Designing Multilingual Applications 6 / 35
17. Locate your user
Parsing accept headers is not hard
Possbile to do by regular expression
Never use geolocation for language selection
Or I’ll get back at you!
Result: de , en GB , cs CZ.UTF-8 , de AU@euro , . . .
Format: langauge[ territory][.codeset][@modifier]
Designing Multilingual Applications 6 / 35
18. Outline
The Dispatcher
The Model
The View
Conclusion
Designing Multilingual Applications 7 / 35
19. The Model
Translation of “user”-provided contents
News, Articles, Products, Comments, . . .
Designing Multilingual Applications 8 / 35
20. Outline
The Model
Model persistance
Domain-Problems
Designing Multilingual Applications 9 / 35
21. One multilingual table
id language state title ...
42 de published Dies ist ein Titel
42 en published This is a title
...
Dublication of non-translated items
De-normalized
Designing Multilingual Applications 10 / 35
22. One multilingual table
id language state title ...
42 de published Dies ist ein Titel
42 en published This is a title
...
Dublication of non-translated items
De-normalized
Designing Multilingual Applications 10 / 35
23. Multiple columns
id state title_1 title_2 ...
42 published Dies ist ein Titel This is a title
...
Limited number of translations
Designing Multilingual Applications 11 / 35
24. Multiple columns
id state title_1 title_2 ...
42 published Dies ist ein Titel This is a title
...
Limited number of translations
Designing Multilingual Applications 11 / 35
25. Multiple tables
id state ...
42 published
...
id language title ...
42 de Dies ist ein Titel
42 en This is a title
...
More complex queries
Designing Multilingual Applications 12 / 35
26. Multiple tables
id state ...
42 published
...
id language title ...
42 de Dies ist ein Titel
42 en This is a title
...
More complex queries
Designing Multilingual Applications 12 / 35
27. Full mapping
Content class Instance Metadata
content_object
content_class id
id content_class_id
name name
content_class_attribute content_object_version
id content_object_version status
content_class_id content_object_id
attribute_type_id id
language_id
name name
status_id
description description
creator
configuration created
default_value
language
id
content_object_data
attribute_type short
content_object_version name
id content_object_id
name language_id
description attribute_id
configuration data
Designing Multilingual Applications 13 / 35
28. Outline
The Model
Model persistance
Domain-Problems
Designing Multilingual Applications 14 / 35
29. The Model
There is a bunch of domain-specific problems
CMS
Different contents
Shop
Tax calculation
Legal requirements
Currency conversions
Others
Recipe aggregation
Designing Multilingual Applications 15 / 35
30. The Model
There is a bunch of domain-specific problems
CMS
Different contents
Shop
Tax calculation
Legal requirements
Currency conversions
Others
Recipe aggregation
Designing Multilingual Applications 15 / 35
31. The Model
There is a bunch of domain-specific problems
CMS
Different contents
Shop
Tax calculation
Legal requirements
Currency conversions
Others
Recipe aggregation
Designing Multilingual Applications 15 / 35
32. The Model
There is a bunch of domain-specific problems
CMS
Different contents
Shop
Tax calculation
Legal requirements
Currency conversions
Others
Recipe aggregation
Designing Multilingual Applications 15 / 35
33. Content (CMS)
Structure of content tree
Each item is translated into all languages
Fallback language
Display sub-tree for non-main languages
Different contents per language
Designing Multilingual Applications 16 / 35
34. Content (CMS)
Structure of content tree
Each item is translated into all languages
Fallback language
Display sub-tree for non-main languages
Different contents per language
Designing Multilingual Applications 16 / 35
35. Content (CMS)
Structure of content tree
Each item is translated into all languages
Fallback language
Display sub-tree for non-main languages
Different contents per language
Designing Multilingual Applications 16 / 35
36. Content (CMS)
Structure of content tree
Each item is translated into all languages
Fallback language
Display sub-tree for non-main languages
Different contents per language
Designing Multilingual Applications 16 / 35
37. Calculations (Shop)
Rule based systems
Select calculation rules based on language / country
IF (@COUNTRY = "us" AND @STATE = "New York") @TAX
= 23.43
IF (@COUNTRY = "de" AND @TYPE = "BOOK") @TAX =
7.00
DEFAULT: @TAX = 19.00
Designing Multilingual Applications 17 / 35
38. Calculations (Shop)
Rule based systems
Select calculation rules based on language / country
IF (@COUNTRY = "us" AND @STATE = "New York") @TAX
= 23.43
IF (@COUNTRY = "de" AND @TYPE = "BOOK") @TAX =
7.00
DEFAULT: @TAX = 19.00
Designing Multilingual Applications 17 / 35
39. Calculations (Shop)
Rule based systems
Select calculation rules based on language / country
IF (@COUNTRY = "us" AND @STATE = "New York") @TAX
= 23.43
IF (@COUNTRY = "de" AND @TYPE = "BOOK") @TAX =
7.00
DEFAULT: @TAX = 19.00
Designing Multilingual Applications 17 / 35
40. Calculations (Shop)
Rule based systems
Select calculation rules based on language / country
IF (@COUNTRY = "us" AND @STATE = "New York") @TAX
= 23.43
IF (@COUNTRY = "de" AND @TYPE = "BOOK") @TAX =
7.00
DEFAULT: @TAX = 19.00
Designing Multilingual Applications 17 / 35
41. Outline
The Dispatcher
The Model
The View
Conclusion
Designing Multilingual Applications 18 / 35
42. Translating strings
gettext()
Depends on setlocale() , which is not thread-safe
QT Linguist
XML based format used in QT
PHP Arrays
PHP Constants
PHP implementation for gettext files
Should not depend on setlocale()
Will be slower
Designing Multilingual Applications 19 / 35
43. Plural forms
Most libraries somehow support plural forms
Support singular
Support simple plural forms
Support different plural forms depending on number
Support multiple words with plural forms in one sentence
Designing Multilingual Applications 20 / 35
44. Plural forms
Most libraries somehow support plural forms
Support singular
Support simple plural forms
Support different plural forms depending on number
Support multiple words with plural forms in one sentence
Designing Multilingual Applications 20 / 35
45. Plural forms
Most libraries somehow support plural forms
Support singular
Support simple plural forms
Support different plural forms depending on number
Support multiple words with plural forms in one sentence
Designing Multilingual Applications 20 / 35
46. Plural forms
Most libraries somehow support plural forms
Support singular
Support simple plural forms
Support different plural forms depending on number
Support multiple words with plural forms in one sentence
Designing Multilingual Applications 20 / 35
47. Finding strings
Locating untranslated strings
Plain strings are “trivial” to find
Parameterized strings are possible to find
Error messages created in applications are impossible to find
Handling untranslated strings
Use proper message as identifier (not MY FOO ERRORMSG1 )
Add “context”
Append strings to storage as “untranslated”
Designing Multilingual Applications 21 / 35
48. Finding strings
Locating untranslated strings
Plain strings are “trivial” to find
Parameterized strings are possible to find
Error messages created in applications are impossible to find
Handling untranslated strings
Use proper message as identifier (not MY FOO ERRORMSG1 )
Add “context”
Append strings to storage as “untranslated”
Designing Multilingual Applications 21 / 35
49. Finding strings
Locating untranslated strings
Plain strings are “trivial” to find
Parameterized strings are possible to find
Error messages created in applications are impossible to find
Handling untranslated strings
Use proper message as identifier (not MY FOO ERRORMSG1 )
Add “context”
Append strings to storage as “untranslated”
Designing Multilingual Applications 21 / 35
50. Finding strings
Locating untranslated strings
Plain strings are “trivial” to find
Parameterized strings are possible to find
Error messages created in applications are impossible to find
Handling untranslated strings
Use proper message as identifier (not MY FOO ERRORMSG1 )
Add “context”
Append strings to storage as “untranslated”
Designing Multilingual Applications 21 / 35
51. Translations
Standardized formats help Translators
Make it easy for them
There are various websites which make collaboration easy
Commonly support QT Linguist and gettext
There is a GUI for QT Linguist translations
Designing Multilingual Applications 22 / 35
54. Outline
The View
Data handling
Designing Multilingual Applications 25 / 35
55. Number formatting
1 <?php
2
3 var dump ( n u m b e r f o r m a t ( 4 2 0 0 0 . 2 3 , 2 ) ) ;
4 // s t r i n g ( 9 ) ” 4 2 , 0 0 0 . 2 3 ”
5
6 var dump ( n u m b e r f o r m a t ( 4 2 0 0 0 . 2 3 , 2 , ’ , ’ , ’ . ’ ) ) ;
7 // s t r i n g ( 9 ) ” 4 2 . 0 0 0 , 2 3 ”
Designing Multilingual Applications 26 / 35
56. Number formatting
1 <?php
2
3 var dump ( n u m b e r f o r m a t ( 4 2 0 0 0 . 2 3 , 2 ) ) ;
4 // s t r i n g ( 9 ) ” 4 2 , 0 0 0 . 2 3 ”
5
6 var dump ( n u m b e r f o r m a t ( 4 2 0 0 0 . 2 3 , 2 , ’ , ’ , ’ . ’ ) ) ;
7 // s t r i n g ( 9 ) ” 4 2 . 0 0 0 , 2 3 ”
Designing Multilingual Applications 26 / 35
57. Number formatting
1 <?php
2
3 var dump ( n u m b e r f o r m a t ( 4 2 0 0 0 . 2 3 , 2 ) ) ;
4 // s t r i n g ( 9 ) ” 4 2 , 0 0 0 . 2 3 ”
5
6 var dump ( n u m b e r f o r m a t ( 4 2 0 0 0 . 2 3 , 2 , ’ , ’ , ’ . ’ ) ) ;
7 // s t r i n g ( 9 ) ” 4 2 . 0 0 0 , 2 3 ”
Designing Multilingual Applications 26 / 35
58. Number formatting
1 <?php
2
3 var dump ( n u m b e r f o r m a t ( 4 2 0 0 0 . 2 3 , 2 ) ) ;
4 // s t r i n g ( 9 ) ” 4 2 , 0 0 0 . 2 3 ”
5
6 var dump ( n u m b e r f o r m a t ( 4 2 0 0 0 . 2 3 , 2 , ’ , ’ , ’ . ’ ) ) ;
7 // s t r i n g ( 9 ) ” 4 2 . 0 0 0 , 2 3 ”
Designing Multilingual Applications 26 / 35
59. Number formatting (Intl)
1 <?php
2
3 $ f o r m a t t e r = new NumberFormatter ( ’ de DE ’ , NumberFormatter : : DECIMAL ) ;
4 var dump ( $ f o r m a t t e r − o r m a t ( 4 2 0 0 0 . 2 3 ) ) ;
>f
5 // s t r i n g ( 9 ) ” 4 2 . 0 0 0 , 2 3 ”
6
7 $ f o r m a t t e r = new NumberFormatter ( ’ en US ’ , NumberFormatter : : SPELLOUT ) ;
8 var dump ( $ f o r m a t t e r − o r m a t ( 4 2 0 0 0 . 2 3 ) ) ;
>f
9 // s t r i n g ( 3 4 ) ” f o r t y −two t h o u s a n d p o i n t two t h r e e ”
Designing Multilingual Applications 27 / 35
60. Number formatting (Intl)
1 <?php
2
3 $ f o r m a t t e r = new NumberFormatter ( ’ de DE ’ , NumberFormatter : : DECIMAL ) ;
4 var dump ( $ f o r m a t t e r − o r m a t ( 4 2 0 0 0 . 2 3 ) ) ;
>f
5 // s t r i n g ( 9 ) ” 4 2 . 0 0 0 , 2 3 ”
6
7 $ f o r m a t t e r = new NumberFormatter ( ’ en US ’ , NumberFormatter : : SPELLOUT ) ;
8 var dump ( $ f o r m a t t e r − o r m a t ( 4 2 0 0 0 . 2 3 ) ) ;
>f
9 // s t r i n g ( 3 4 ) ” f o r t y −two t h o u s a n d p o i n t two t h r e e ”
Designing Multilingual Applications 27 / 35
61. Number formatting (Intl)
1 <?php
2
3 $ f o r m a t t e r = new NumberFormatter ( ’ de DE ’ , NumberFormatter : : DECIMAL ) ;
4 var dump ( $ f o r m a t t e r − o r m a t ( 4 2 0 0 0 . 2 3 ) ) ;
>f
5 // s t r i n g ( 9 ) ” 4 2 . 0 0 0 , 2 3 ”
6
7 $ f o r m a t t e r = new NumberFormatter ( ’ en US ’ , NumberFormatter : : SPELLOUT ) ;
8 var dump ( $ f o r m a t t e r − o r m a t ( 4 2 0 0 0 . 2 3 ) ) ;
>f
9 // s t r i n g ( 3 4 ) ” f o r t y −two t h o u s a n d p o i n t two t h r e e ”
Designing Multilingual Applications 27 / 35
62. Number formatting (Intl)
1 <?php
2
3 $ f o r m a t t e r = new NumberFormatter ( ’ de DE ’ , NumberFormatter : : DECIMAL ) ;
4 var dump ( $ f o r m a t t e r − o r m a t ( 4 2 0 0 0 . 2 3 ) ) ;
>f
5 // s t r i n g ( 9 ) ” 4 2 . 0 0 0 , 2 3 ”
6
7 $ f o r m a t t e r = new NumberFormatter ( ’ en US ’ , NumberFormatter : : SPELLOUT ) ;
8 var dump ( $ f o r m a t t e r − o r m a t ( 4 2 0 0 0 . 2 3 ) ) ;
>f
9 // s t r i n g ( 3 4 ) ” f o r t y −two t h o u s a n d p o i n t two t h r e e ”
Designing Multilingual Applications 27 / 35
63. Date formatting
1 <?php
2
3 $time = 1234567890;
4
5 var dump ( s t r f t i m e ( ’%A , %e . %B %G − %I :%M %P ’ , $ t i m e ) ) ;
6 // s t r i n g ( 3 8 ) ” S a t u r d a y , 1 4 . F e b r u a r y 2009 − 1 2 : 3 1 am”
7
8 s e t l o c a l e ( LC TIME , ’ de ’ , ’ de DE ’ , ’ de DE . UTF−8 ’ , ’ deu ’ ) ;
9 var dump ( s t r f t i m e ( ’%A , %e . %B %G − %H:%M’ , $ t i m e ) ) ;
10 // s t r i n g ( 3 3 ) ” Samstag , 1 4 . F e b r u a r 2009 − 0 0 : 3 1 ”
Designing Multilingual Applications 28 / 35
64. Date formatting
1 <?php
2
3 $time = 1234567890;
4
5 var dump ( s t r f t i m e ( ’%A , %e . %B %G − %I :%M %P ’ , $ t i m e ) ) ;
6 // s t r i n g ( 3 8 ) ” S a t u r d a y , 1 4 . F e b r u a r y 2009 − 1 2 : 3 1 am”
7
8 s e t l o c a l e ( LC TIME , ’ de ’ , ’ de DE ’ , ’ de DE . UTF−8 ’ , ’ deu ’ ) ;
9 var dump ( s t r f t i m e ( ’%A , %e . %B %G − %H:%M’ , $ t i m e ) ) ;
10 // s t r i n g ( 3 3 ) ” Samstag , 1 4 . F e b r u a r 2009 − 0 0 : 3 1 ”
Designing Multilingual Applications 28 / 35
65. Date formatting
1 <?php
2
3 $time = 1234567890;
4
5 var dump ( s t r f t i m e ( ’%A , %e . %B %G − %I :%M %P ’ , $ t i m e ) ) ;
6 // s t r i n g ( 3 8 ) ” S a t u r d a y , 1 4 . F e b r u a r y 2009 − 1 2 : 3 1 am”
7
8 s e t l o c a l e ( LC TIME , ’ de ’ , ’ de DE ’ , ’ de DE . UTF−8 ’ , ’ deu ’ ) ;
9 var dump ( s t r f t i m e ( ’%A , %e . %B %G − %H:%M’ , $ t i m e ) ) ;
10 // s t r i n g ( 3 3 ) ” Samstag , 1 4 . F e b r u a r 2009 − 0 0 : 3 1 ”
Designing Multilingual Applications 28 / 35
66. Date formatting
1 <?php
2
3 $time = 1234567890;
4
5 var dump ( s t r f t i m e ( ’%A , %e . %B %G − %I :%M %P ’ , $ t i m e ) ) ;
6 // s t r i n g ( 3 8 ) ” S a t u r d a y , 1 4 . F e b r u a r y 2009 − 1 2 : 3 1 am”
7
8 s e t l o c a l e ( LC TIME , ’ de ’ , ’ de DE ’ , ’ de DE . UTF−8 ’ , ’ deu ’ ) ;
9 var dump ( s t r f t i m e ( ’%A , %e . %B %G − %H:%M’ , $ t i m e ) ) ;
10 // s t r i n g ( 3 3 ) ” Samstag , 1 4 . F e b r u a r 2009 − 0 0 : 3 1 ”
Designing Multilingual Applications 28 / 35
67. Date formatting (Intl)
1 <?php
2
3 $time = 1234567890;
4
5 $ f o r m a t t e r = new I n t l D a t e F o r m a t t e r (
6 ’ en ’ ,
7 I n t l D a t e F o r m a t t e r : : FULL , // d a t e
8 I n t l D a t e F o r m a t t e r : : SHORT // t i m e
9 );
10 var dump ( $ f o r m a t t e r − o r m a t ( $ t i m e ) ) ;
>f
11 // s t r i n g ( 3 6 ) ” S a t u r d a y , F e b r u a r y 1 4 , 2009 1 2 : 3 1 AM”
12
13 $ f o r m a t t e r = new I n t l D a t e F o r m a t t e r (
14 ’ de DE ’ ,
15 I n t l D a t e F o r m a t t e r : : FULL , // d a t e
16 I n t l D a t e F o r m a t t e r : : SHORT // t i m e
17 );
18 var dump ( $ f o r m a t t e r − o r m a t ( $ t i m e ) ) ;
>f
19 // s t r i n g ( 3 1 ) ” Samstag , 1 4 . F e b r u a r 2009 0 0 : 3 1 ”
Designing Multilingual Applications 29 / 35
68. Date formatting (Intl)
1 <?php
2
3 $time = 1234567890;
4
5 $ f o r m a t t e r = new I n t l D a t e F o r m a t t e r (
6 ’ en ’ ,
7 I n t l D a t e F o r m a t t e r : : FULL , // d a t e
8 I n t l D a t e F o r m a t t e r : : SHORT // t i m e
9 );
10 var dump ( $ f o r m a t t e r − o r m a t ( $ t i m e ) ) ;
>f
11 // s t r i n g ( 3 6 ) ” S a t u r d a y , F e b r u a r y 1 4 , 2009 1 2 : 3 1 AM”
12
13 $ f o r m a t t e r = new I n t l D a t e F o r m a t t e r (
14 ’ de DE ’ ,
15 I n t l D a t e F o r m a t t e r : : FULL , // d a t e
16 I n t l D a t e F o r m a t t e r : : SHORT // t i m e
17 );
18 var dump ( $ f o r m a t t e r − o r m a t ( $ t i m e ) ) ;
>f
19 // s t r i n g ( 3 1 ) ” Samstag , 1 4 . F e b r u a r 2009 0 0 : 3 1 ”
Designing Multilingual Applications 29 / 35
69. Date formatting (Intl)
1 <?php
2
3 $time = 1234567890;
4
5 $ f o r m a t t e r = new I n t l D a t e F o r m a t t e r (
6 ’ en ’ ,
7 I n t l D a t e F o r m a t t e r : : FULL , // d a t e
8 I n t l D a t e F o r m a t t e r : : SHORT // t i m e
9 );
10 var dump ( $ f o r m a t t e r − o r m a t ( $ t i m e ) ) ;
>f
11 // s t r i n g ( 3 6 ) ” S a t u r d a y , F e b r u a r y 1 4 , 2009 1 2 : 3 1 AM”
12
13 $ f o r m a t t e r = new I n t l D a t e F o r m a t t e r (
14 ’ de DE ’ ,
15 I n t l D a t e F o r m a t t e r : : FULL , // d a t e
16 I n t l D a t e F o r m a t t e r : : SHORT // t i m e
17 );
18 var dump ( $ f o r m a t t e r − o r m a t ( $ t i m e ) ) ;
>f
19 // s t r i n g ( 3 1 ) ” Samstag , 1 4 . F e b r u a r 2009 0 0 : 3 1 ”
Designing Multilingual Applications 29 / 35
70. Date formatting (Intl)
1 <?php
2
3 $time = 1234567890;
4
5 $ f o r m a t t e r = new I n t l D a t e F o r m a t t e r (
6 ’ en ’ ,
7 I n t l D a t e F o r m a t t e r : : FULL , // d a t e
8 I n t l D a t e F o r m a t t e r : : SHORT // t i m e
9 );
10 var dump ( $ f o r m a t t e r − o r m a t ( $ t i m e ) ) ;
>f
11 // s t r i n g ( 3 6 ) ” S a t u r d a y , F e b r u a r y 1 4 , 2009 1 2 : 3 1 AM”
12
13 $ f o r m a t t e r = new I n t l D a t e F o r m a t t e r (
14 ’ de DE ’ ,
15 I n t l D a t e F o r m a t t e r : : FULL , // d a t e
16 I n t l D a t e F o r m a t t e r : : SHORT // t i m e
17 );
18 var dump ( $ f o r m a t t e r − o r m a t ( $ t i m e ) ) ;
>f
19 // s t r i n g ( 3 1 ) ” Samstag , 1 4 . F e b r u a r 2009 0 0 : 3 1 ”
Designing Multilingual Applications 29 / 35
73. Charsets & Encodings
Use UTF-8
Also see: http://www.kore-nordmann.de/blog/php_
charset_encoding_FAQ.html
Designing Multilingual Applications 32 / 35
74. Charsets & Encodings
Use UTF-8
Also see: http://www.kore-nordmann.de/blog/php_
charset_encoding_FAQ.html
Designing Multilingual Applications 32 / 35
75. Outline
The Dispatcher
The Model
The View
Conclusion
Designing Multilingual Applications 33 / 35
76. Conclusion
There are really tricky domain specific problems
Use solutions not depending on setlocale()
Use intl extension if possible
Designing Multilingual Applications 34 / 35
77. Thanks for listening
Please rate this talk at
http://joind.in/3491
and (optionally) give us some feedback right now
Designing Multilingual Applications 35 / 35
78. Thanks for listening
Please rate this talk at
http://joind.in/3491
and (optionally) give us some feedback right now
This is very important for . . .
Speakers
Organizers
You!
Designing Multilingual Applications 35 / 35
79. Thanks for listening
Please rate this talk at
http://joind.in/3491
and (optionally) give us some feedback right now
Stay in touch
Kore Nordmann
kore@qafoo.com
@koredn / @qafoo
Rent a PHP quality expert:
http://qafoo.com
Designing Multilingual Applications 35 / 35