No subject
Tue Feb 1 14:29:29 CET 2011
Vous avez #{toPlural 'chien' (maleDogs myBasket)} et #{femaleCats 'chatte' myBasket)} dans votre charrette.
This would be pluralized by chien being run through a pluralization engine if necessary
I know my thinking is rough so far since you've obviously given it a lot of thought, but does my concept make sense?
--
Ian Duncan
On Monday, February 21, 2011 at 1:20 AM, Michael Snoyman wrote:
> Let's look at a more concrete example: you have an online store
> selling male dogs and female cats. So you would have:
>
> data Basket = Basket { maleDogs :: Int, femaleCats :: Int }
>
> What you need is a function such as:
>
> renderBasket :: Basket -> String
>
> for each language. In English, this could be something like:
>
> pluralize :: Int -> (String, String) -> String
> pluralize 1 (x, _) = x
> pluralize _ (_, x) = x
>
> renderBasket (Basket dogs cats) = concat
> [ "You have decided to purchase "
> , show dogs
> , pluralize dogs ("dog", "dogs")
> , " and "
> , show cats
> , pluralize cats ("cat", "cats")
> ]
>
> In Hebrew, some words (like years) have a singular, plural *and* dual
> form, so pluralize for Hebrew may look like:
>
> pluralize :: Int -> (String, Maybe String, String) -> String
> pluralize 1 (x, _, _) = x ++ " ×××" -- in Hebrew, the "one" comes
> after the word, all other numbers before
> pluralize 2 (_, Just x, _) = x -- for dual form, you never show
> the number, it is assumed
> pluralize i (_, _, x) = show i ++ " " ++ x -- for the plural, put
> the number before
>
> If we could build up a library in Haskell of such helper functions, I
> think it would make translating applications much simpler. But this is
> the point where we would need a lot of collaboration: I can help out
> on English and Hebrew (and if I still remember it, Spanish), but I
> don't know a thing about Japanese, Russian, or most other languages in
> the world.
>
> I'm not sure how much it would really help to use typeclasses here,
> however. I think for the most part it will just be an issue of having
> a separate module for each language. What I'd *really* like to figure
> out is how to make a nice, easy-to-use wrapper around all of this for
> translators, who will likely not know any Haskell. Perhaps a language
> similar to Hamlet:
>
> # strings-english.trans
> Hello: Hello
> Person name age: #{name} is #{age} #{pluralize age "year" "years"} old.
> Basket dogs cats: You have purchased #{dogs} #{pluralize dogs
> "dog" "dogs"} and #{cats} #{pluralize cats "cat" cats"}.
>
> Michael
>
> On Mon, Feb 21, 2011 at 8:57 AM, Ian Duncan <iand675 at gmail.com> wrote:
> > And of course in some languages such as Japanese, there are barely any
> > gender distinctions or such things as pluralization at all. Perhaps we need
> > pluralization, conjugation, and 'genderization' typeclasses with instances
> > defined for different language datatypes?
> >
> > --
> > Ian Duncan
> >
> > On Monday, February 21, 2011 at 12:46 AM, Michael Snoyman wrote:
> >
> > The other day I was speaking with a woman on the train. She was
> > telling me about her daughters. I wanted to ask her how old they are,
> > but I got the pluralization wrong and instead of saying "bnot kama"
> > (plural) I said "bat kama," (singular) to which she responded 36.
> >
> > tl;dr: You can offend people just was well with pluralization issues
> > as with gender issues.
> >
> > Michael
> >
> > On Mon, Feb 21, 2011 at 8:40 AM, Max Cantor <mxcantor at gmail.com> wrote:
> >
> > Of course, you just pointed out one of the big difficulties with i18n. I
> > dont think you're wife would take kindly to you referring to her in the male
> > gender. so now, you need the person's gender too. i18n is hard :( the
> > whole would should switch to esperanto.
> >
> > max
> >
> > On Feb 21, 2011, at 2:25 PM, Michael Snoyman wrote:
> >
> > A proper i18n solution is high on my wish list right now, but I've
> > purposely avoided implementing one so far since I'd rather wait until
> > I think we have a good solution as opposed to implementing an
> > acceptable solution now. But let me share my ideas, it might help you
> > out here.
> >
> > In general, it's very uncommon that you need a completely separate set
> > of templates for each language. Your markup, classes, styles, and
> > logic will likely be identical for each language, and creating a
> > separate template for each will just result in a lot of pain in the
> > long run. Instead, you're likely better off having a single template
> > and just translating strings.
> >
> > I've blogged about this before[1]. My idea is to use a datatype for
> > your translatable strings, and then have a function that takes a
> > language and a value and returns the translated string. A simple
> > example:
> >
> > data Strings = Hello | Person String Int
> > toEnglish Hello = "Hello"
> > toEnglish (Person name age) = name ++ " is " ++ show age ++ "
> > years old" -- obviously need to check if person is 1 year old and
> > correct
> >
> > toHebrew Hello = "ש×××"
> > toHebrew (Person name age) = name ++ " ××× ×× " ++ show age ++ " ×©× ××"
> >
> > The nice thing about this approach is you have the full power of
> > Haskell to address typical translation issues, such as pluralization,
> > word order and gender matching. (As a counter example, at work, we use
> > XSLT for this, and then you get the full power of XSLT for solving the
> > problem ::cringe::.)
> >
> > You can then use the languages[2] function from Yesod to help you out:
> >
> > getRenderString = chooseFunc `fmap` languages
> > where
> > chooseFunc [] = toEnglish -- default language
> > chooseFunc ("en":_) = toEnglish
> > chooseFunc ("he":_) = toHebrew
> > chooseFunc (_:x) = chooseFunc x
> >
> > Then you can write a handler function like:
> >
> > getPersonR name age = do
> > render <- getRenderString
> > defaultLayout [$hamlet|
> > <h1>#{render Hello}
> > <p>#{render $ Person name age}
> > |]
> >
> > Which will work for English and Hebrew just fine. Ideally, I would
> > like to add support to Hamlet for this directly, involving a String
> > rendering function similar to the URL rendering function already in
> > place. But for the moment, this should work.
> >
> > I'd love to hear peoples opinions about this.
> >
> > Michael
> >
> > [1] http://docs.yesodweb.com/blog/i18n-in-haskell
> > [2]
> > http://hackage.haskell.org/packages/archive/yesod-core/0.7.0.1/doc/html/Yesod-Request.html#v:languages
> >
> > On Sun, Feb 20, 2011 at 11:19 PM, Dmitry Kurochkin
> > <dmitry.kurochkin at gmail.com> wrote:
> >
> > Hi all.
> >
> > I want a handler to render different templates for different languages.
> > I have getCurrentLanguage function and now I try to do something like:
> >
> > getRootR = do
> > currentLanguage <- getCurrentLanguage
> > defaultLayout $ do
> > addWidget $(widgetFile $ currentLanguage ++ "/homepage")
> >
> > This results in:
> >
> > GHC stage restriction: `currentLanguage'
> > is used in a top-level splice or annotation,
> > and must be imported, not defined locally
> >
> > This makes sense to me, because TH is calculated at compile time. I
> > would like to hear ideas how to work around this restriction. Perhaps
> > there is an existing solution in Yesod?
> >
> > At the moment, the best I could think of is smth like this:
> >
> > getRootR = do
> > currentLanguage <- getCurrentLanguage
> > defaultLayout $ do
> > case currentLanguage of
> > "en" -> addWidget $(widgetFile "en/homepage")
> > ... and so on for each language ...
> >
> > Obviously, this is not a solution taking in account that there are many
> > languages and many handlers.
> >
> > I was considering creating a global (template file name -> rendered
> > template) map. But I am not sure this is really feasible.
> >
> > Regards,
> > Dmitry
> >
> > _______________________________________________
> > web-devel mailing list
> > web-devel at haskell.org
> > http://www.haskell.org/mailman/listinfo/web-devel
> >
> > _______________________________________________
> > web-devel mailing list
> > web-devel at haskell.org
> > http://www.haskell.org/mailman/listinfo/web-devel
> >
> > _______________________________________________
> > web-devel mailing list
> > web-devel at haskell.org
> > http://www.haskell.org/mailman/listinfo/web-devel
>
--4d621650_98a3148_139
Content-Type: text/html; charset="utf-8"
Content-Transfer-Encoding: quoted-printable
Content-Disposition: inline
<div>
<div>
<span>My reasoning for typeclasses is this:<div>Keep in m=
ind this is just a mental exercise, not saying that this would compile...=
</div><div>Suppose for your example we wanted to translate it into french=
:</div><div><br></div><div>-- Nouns for languages have some way to decide=
gender, if that matters for the given language</div><div>class Translate=
a where</div><div>toPlural :: Noun a -> Int -> =5BWords a=5D</div>=
<div><br></div><div>data =46rench =3D =46rench =7B</div><div> =
... stuff ...</div><div> languageCode =3D =22=46=
R=22</div><div>=7D</div><div><br></div><div>instance Translate =46rench w=
here</div><div>toPlural =3D frenchPluralizationEngine</div><div><br></div=
><div>=46rom there we go with something like your .trans files: we give e=
ach language the extension according to their language code. So basket.fr=
is the french translation:</div><div><br></div><div>Vous avez =23=7BtoPl=
ural 'chien' (maleDogs myBasket)=7D et =23=7BfemaleCats 'chatte' myBasket=
)=7D dans votre charrette.</div><div><br></div><div>This would be plurali=
zed by chien being run through a pluralization engine if necessary <=
/div><div>I know my thinking is rough so far since you've obviously given=
it a lot of thought, but does my concept make sense=3F</div></span>
<span><br>-- <br>Ian Duncan<br><br></span>
=20
<p style=3D=22color: =23a0a0a0;=22>On Monday, =46ebruary =
21, 2011 at 1:20 AM, Michael Snoyman wrote:</p>
<blockquote type=3D=22cite=22 style=3D=22border-left-styl=
e:solid;border-width:1px;margin-left:0px;padding-left:10px;=22>
<span><div><div>Let's look at a more concrete example=
: you have an online store<br>selling male dogs and female cats. So you w=
ould have:<br><br> data Basket =3D Basket =7B maleDogs :: Int, femaleC=
ats :: Int =7D<br><br>What you need is a function such as:<br><br> ren=
derBasket :: Basket -> String<br><br>for each language. In English, th=
is could be something like:<br><br> pluralize :: Int -> (String, St=
ring) -> String<br> pluralize 1 (x, =5F) =3D x<br> pluralize =5F=
(=5F, x) =3D x<br><br> renderBasket (Basket dogs cats) =3D concat<br>=
=5B =22You have decided to purchase =22<br> , show dogs<br=
> , pluralize dogs (=22dog=22, =22dogs=22)<br> , =22 and =22=
<br> , show cats<br> , pluralize cats (=22cat=22, =22cats=22=
)<br> =5D<br><br>In Hebrew, some words (like years) have a singula=
r, plural *and* dual<br>form, so pluralize for Hebrew may look like:<br><=
br> pluralize :: Int -> (String, Maybe String, String) -> String=
<br> pluralize 1 (x, =5F, =5F) =3D x ++ =22 =D7=90=D7=97=D7=93=22 -- i=
n Hebrew, the =22one=22 comes<br>after the word, all other numbers before=
<br> pluralize 2 (=5F, Just x, =5F) =3D x -- for dual form, you never =
show<br>the number, it is assumed<br> pluralize i (=5F, =5F, x) =3D sh=
ow i ++ =22 =22 ++ x -- for the plural, put<br>the number before<br><br>I=
f we could build up a library in Haskell of such helper functions, I<br>t=
hink it would make translating applications much simpler. But this is<br>=
the point where we would need a lot of collaboration: I can help out<br>o=
n English and Hebrew (and if I still remember it, Spanish), but I<br>don'=
t know a thing about Japanese, Russian, or most other languages in<br>the=
world.<br><br>I'm not sure how much it would really help to use typeclas=
ses here,<br>however. I think for the most part it will just be an issue =
of having<br>a separate module for each language. What I'd *really* like =
to figure<br>out is how to make a nice, easy-to-use wrapper around all of=
this for<br>translators, who will likely not know any Haskell. Perhaps a=
language<br>similar to Hamlet:<br><br> =23 strings-english.trans<br> =
Hello: Hello<br> Person name age: #=23=7Bname=7D is =23=7Bage=7D =23=
=7Bpluralize age =22year=22 =22years=22=7D old.<br> Basket dogs cats: =
You have purchased =23=7Bdogs=7D =23=7Bpluralize dogs<br>=22dog=22 =22dog=
s=22=7D and =23=7Bcats=7D =23=7Bpluralize cats =22cat=22 cats=22=7D.<br><=
br>Michael<br><br>On Mon, =46eb 21, 2011 at 8:57 AM, Ian Duncan <<a hr=
ef=3D=22mailto:iand675=40gmail.com=22>iand675=40gmail.com</a>> wrote:<=
br><blockquote type=3D=22cite=22><div>And of course in some languages suc=
h as Japanese, there are barely any<br>gender distinctions or such things=
as pluralization at all. Perhaps we need<br>pluralization, conjugation, =
and 'genderization' typeclasses with instances<br>defined for different l=
anguage datatypes=3F<br><br>--<br>Ian Duncan<br><br>On Monday, =46ebruary=
21, 2011 at 12:46 AM, Michael Snoyman wrote:<br><br>The other day I was =
speaking with a woman on the train. She was<br>telling me about her daugh=
ters. I wanted to ask her how old they are,<br>but I got the pluralizatio=
n wrong and instead of saying =22bnot kama=22<br>(plural) I said =22bat k=
ama,=22 (singular) to which she responded 36.<br><br>tl;dr: You can offen=
d people just was well with pluralization issues<br>as with gender issues=
.<br><br>Michael<br><br>On Mon, =46eb 21, 2011 at 8:40 AM, Max Cantor <=
;<a href=3D=22mailto:mxcantor=40gmail.com=22>mxcantor=40gmail.com</a>>=
wrote:<br><br>Of course, you just pointed out one of the big difficultie=
s with i18n. I<br>dont think you're wife would take kindly to you r=
eferring to her in the male<br>gender. so now, you need the person'=
s gender too. i18n is hard :( the<br>whole would should switc=
h to esperanto.<br><br>max<br><br>On =46eb 21, 2011, at 2:25 PM, Michael =
Snoyman wrote:<br><br>A proper i18n solution is high on my wish list righ=
t now, but I've<br>purposely avoided implementing one so far since I'd ra=
ther wait until<br>I think we have a good solution as opposed to implemen=
ting an<br>acceptable solution now. But let me share my ideas, it might h=
elp you<br>out here.<br><br>In general, it's very uncommon that you need =
a completely separate set<br>of templates for each language. Your markup,=
classes, styles, and<br>logic will likely be identical for each language=
, and creating a<br>separate template for each will just result in a lot =
of pain in the<br>long run. Instead, you're likely better off having a si=
ngle template<br>and just translating strings.<br><br>I've blogged about =
this before=5B1=5D. My idea is to use a datatype for<br>your translatable=
strings, and then have a function that takes a<br>language and a value a=
nd returns the translated string. A simple<br>example:<br><br> &nbs=
p;data Strings =3D Hello =7C Person String Int<br> toEnglish =
Hello =3D =22Hello=22<br> toEnglish (Person name age) =3D nam=
e ++ =22 is =22 ++ show age ++ =22<br>years old=22 -- obviously need to c=
heck if person is 1 year old and<br>correct<br><br> toHebrew =
Hello =3D =22=D7=A9=D7=9C=D7=95=D7=9D=22<br> toHebrew (Person=
name age) =3D name ++ =22 =D7=94=D7=95=D7=90 =D7=91=D7=9F =22 ++ show ag=
e ++ =22 =D7=A9=D7=A0=D7=99=D7=9D=22<br><br>The nice thing about this app=
roach is you have the full power of<br>Haskell to address typical transla=
tion issues, such as pluralization,<br>word order and gender matching. (A=
s a counter example, at work, we use<br>XSLT for this, and then you get t=
he full power of XSLT for solving the<br>problem ::cringe::.)<br><br>You =
can then use the languages=5B2=5D function from Yesod to help you out:<br=
><br> getRenderString =3D choose=46unc =60fmap=60 languages<b=
r> where<br> choose=46unc =
=5B=5D =3D toEnglish -- default language<br> c=
hoose=46unc (=22en=22:=5F) =3D toEnglish<br> c=
hoose=46unc (=22he=22:=5F) =3D toHebrew<br> ch=
oose=46unc (=5F:x) =3D choose=46unc x<br><br>Then you can write a handler=
function like:<br><br>getPersonR name age =3D do<br> render =
<- getRenderString<br> defaultLayout =5B=24hamlet=7C<br>&l=
t;h1>=23=7Brender Hello=7D<br><p>=23=7Brender =24 Person name ag=
e=7D<br>=7C=5D<br><br>Which will work for English and Hebrew just fine. I=
deally, I would<br>like to add support to Hamlet for this directly, invol=
ving a String<br>rendering function similar to the URL rendering function=
already in<br>place. But for the moment, this should work.<br><br>I'd lo=
ve to hear peoples opinions about this.<br><br>Michael<br><br>=5B1=5D <a =
href=3D=22http://docs.yesodweb.com/blog/i18n-in-haskell=22>http://docs.ye=
sodweb.com/blog/i18n-in-haskell</a><br>=5B2=5D<br><a href=3D=22http://hac=
kage.haskell.org/packages/archive/yesod-core/0.7.0.1/doc/html/Yesod-Reque=
st.html=23v:languages=22>http://hackage.haskell.org/packages/archive/yeso=
d-core/0.7.0.1/doc/html/Yesod-Request.html=23v:languages</a><br><br>On Su=
n, =46eb 20, 2011 at 11:19 PM, Dmitry Kurochkin<br><<a href=3D=22mailt=
o:dmitry.kurochkin=40gmail.com=22>dmitry.kurochkin=40gmail.com</a>> wr=
ote:<br><br>Hi all.<br><br>I want a handler to render different templates=
for different languages.<br>I have getCurrentLanguage function and now I=
try to do something like:<br><br> getRootR =3D do<br> =
currentLanguage <- getCurrentLanguage<br> &n=
bsp; defaultLayout =24 do<br> &nb=
sp; addWidget =24(widget=46ile =24 currentLanguage ++ =22/homepage=22=
)<br><br>This results in:<br><br> GHC stage restriction: =60c=
urrentLanguage'<br> is used in a top-level splice or a=
nnotation,<br> and must be imported, not defined local=
ly<br><br>This makes sense to me, because TH is calculated at compile tim=
e. I<br>would like to hear ideas how to work around this restriction. Per=
haps<br>there is an existing solution in Yesod=3F<br><br>At the moment, t=
he best I could think of is smth like this:<br><br> getRootR =
=3D do<br> currentLanguage <- getCurrentLang=
uage<br> defaultLayout =24 do<br> =
case currentLanguage of<br>  =
; =22en=22 -> addWidget =24(widget=46=
ile =22en/homepage=22)<br> =
... and so on for each language ...<br><br>Obviously, this =
is not a solution taking in account that there are many<br>languages and =
many handlers.<br><br>I was considering creating a global (template file =
name -> rendered<br>template) map. But I am not sure this is really fe=
asible.<br><br>Regards,<br> Dmitry<br><br>=5F=5F=5F=5F=5F=5F=5F=5F=5F=
=5F=5F=5F=5F=5F=5F=5F=5F=5F=5F=5F=5F=5F=5F=5F=5F=5F=5F=5F=5F=5F=5F=5F=5F=5F=
=5F=5F=5F=5F=5F=5F=5F=5F=5F=5F=5F=5F=5F<br>web-devel mailing list<br><a h=
ref=3D=22mailto:web-devel=40haskell.org=22>web-devel=40haskell.org</a><br=
><a href=3D=22http://www.haskell.org/mailman/listinfo/web-devel=22>http:/=
/www.haskell.org/mailman/listinfo/web-devel</a><br><br>=5F=5F=5F=5F=5F=5F=
=5F=5F=5F=5F=5F=5F=5F=5F=5F=5F=5F=5F=5F=5F=5F=5F=5F=5F=5F=5F=5F=5F=5F=5F=5F=
=5F=5F=5F=5F=5F=5F=5F=5F=5F=5F=5F=5F=5F=5F=5F=5F<br>web-devel mailing lis=
t<br><a href=3D=22mailto:web-devel=40haskell.org=22>web-devel=40haskell.o=
rg</a><br><a href=3D=22http://www.haskell.org/mailman/listinfo/web-devel=22=
>http://www.haskell.org/mailman/listinfo/web-devel</a><br><br>=5F=5F=5F=5F=
=5F=5F=5F=5F=5F=5F=5F=5F=5F=5F=5F=5F=5F=5F=5F=5F=5F=5F=5F=5F=5F=5F=5F=5F=5F=
=5F=5F=5F=5F=5F=5F=5F=5F=5F=5F=5F=5F=5F=5F=5F=5F=5F=5F<br>web-devel maili=
ng list<br><a href=3D=22mailto:web-devel=40haskell.org=22>web-devel=40has=
kell.org</a><br><a href=3D=22http://www.haskell.org/mailman/listinfo/web-=
devel=22>http://www.haskell.org/mailman/listinfo/web-devel</a><br></div><=
/blockquote></div></div></span>
=20
=20
=20
=20
</blockquote>
=20
<div>
<br>
</div>
</div>
</div>
--4d621650_98a3148_139--
More information about the web-devel
mailing list