Page Menu
Home
c4science
Search
Configure Global Search
Log In
Files
F103515554
PhutilTranslator.php
No One
Temporary
Actions
Download File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Award Token
Subscribers
None
File Metadata
Details
File Info
Storage
Attached
Created
Sun, Mar 2, 16:04
Size
4 KB
Mime Type
text/x-php
Expires
Tue, Mar 4, 16:04 (2 d)
Engine
blob
Format
Raw Data
Handle
24600792
Attached To
rPHU libphutil
PhutilTranslator.php
View Options
<?php
/**
* @group internationalization
*/
final
class
PhutilTranslator
{
static
private
$instance
;
private
$language
=
'en'
;
private
$translations
=
array
();
public
static
function
getInstance
()
{
if
(
self
::
$instance
===
null
)
{
self
::
$instance
=
new
PhutilTranslator
();
}
return
self
::
$instance
;
}
public
static
function
setInstance
(
PhutilTranslator
$instance
)
{
self
::
$instance
=
$instance
;
}
public
function
setLanguage
(
$language
)
{
$this
->
language
=
$language
;
return
$this
;
}
/**
* Add translations which will be later used by @{method:translate}.
* The parameter is an array of strings (for simple translations) or arrays
* (for translastions with variants). The number of items in the array is
* language specific. It is `array($singular, $plural)` for English.
*
* array(
* 'color' => 'colour',
* '%d beer(s)' => array('%d beer', '%d beers'),
* );
*
* The arrays can be nested for strings with more variant parts:
*
* array(
* '%d char(s) on %d row(s)' => array(
* array('%d char on %d row', '%d char on %d rows'),
* array('%d chars on %d row', '%d chars on %d rows'),
* ),
* );
*
* The translation should have the same placeholders as originals. Swapping
* parameter order is possible:
*
* array(
* '%s owns %s.' => '%2$s is owned by %1$s.',
* );
*
* @param array Identifier in key, translation in value.
* @return PhutilTranslator Provides fluent interface.
*/
public
function
addTranslations
(
array
$translations
)
{
$this
->
translations
=
array_merge
(
$this
->
translations
,
$translations
);
return
$this
;
}
public
function
translate
(
$text
/* , ... */
)
{
$translation
=
idx
(
$this
->
translations
,
$text
,
$text
);
$args
=
func_get_args
();
while
(
is_array
(
$translation
))
{
$translation
=
$this
->
chooseVariant
(
$translation
,
next
(
$args
));
}
array_shift
(
$args
);
return
vsprintf
(
$translation
,
$args
);
}
private
function
chooseVariant
(
array
$translations
,
$variant
)
{
switch
(
$this
->
language
)
{
case
'en'
:
list
(
$singular
,
$plural
)
=
$translations
;
if
(
$variant
==
1
)
{
return
$singular
;
}
return
$plural
;
case
'cs'
:
if
(
$variant
instanceof
PhutilPerson
)
{
list
(
$male
,
$female
)
=
$translations
;
if
(
$variant
->
getSex
()
==
PhutilPerson
::
SEX_FEMALE
)
{
return
$female
;
}
return
$male
;
}
list
(
$singular
,
$paucal
,
$plural
)
=
$translations
;
if
(
$variant
==
1
)
{
return
$singular
;
}
if
(
$variant
>=
2
&&
$variant
<=
4
)
{
return
$paucal
;
}
return
$plural
;
default
:
throw
new
Exception
(
"Unknown language '{$this->language}'."
);
}
}
/**
* Translate date formatted by `$date->format()`.
*
* @param string Format accepted by `DateTime::format()`.
* @param DateTime
* @return string Formatted and translated date.
*/
public
function
translateDate
(
$format
,
DateTime
$date
)
{
static
$format_cache
=
array
();
if
(!
isset
(
$format_cache
[
$format
]))
{
$translatable
=
'DlSFMaA'
;
preg_match_all
(
'/['
.
$translatable
.
']|(
\\\\
.|[^'
.
$translatable
.
'])+/'
,
$format
,
$format_cache
[
$format
],
PREG_SET_ORDER
);
}
$parts
=
array
();
foreach
(
$format_cache
[
$format
]
as
$match
)
{
$part
=
$date
->
format
(
$match
[
0
]);
if
(!
isset
(
$match
[
1
]))
{
$part
=
$this
->
translate
(
$part
);
}
$parts
[]
=
$part
;
}
return
implode
(
''
,
$parts
);
}
public
function
validateTranslation
(
$original
,
$translation
)
{
$pattern
=
'/<(
\S
[^>]*>?)?|&(
\S
[^;]*;?)?/i'
;
$original_matches
=
null
;
$translation_matches
=
null
;
preg_match_all
(
$pattern
,
$original
,
$original_matches
);
preg_match_all
(
$pattern
,
$translation
,
$translation_matches
);
sort
(
$original_matches
[
0
]);
sort
(
$translation_matches
[
0
]);
if
(
$original_matches
[
0
]
!==
$translation_matches
[
0
])
{
return
false
;
}
return
true
;
}
}
Event Timeline
Log In to Comment