WN

WN (https://www.wn.se/forum/index.php)
-   Serversidans teknologier (https://www.wn.se/forum/forumdisplay.php?f=4)
-   -   Finns det bra metoder för flerspråkig site? (https://www.wn.se/forum/showthread.php?t=24177)

totoo 2007-10-09 14:56

Jag har gjort flerspråkiga siter förr, men jag har aldrig kommit fram till någon bra struktur.
Finns det överhuvudtaget någon klockren lösning för flerspråkiga siter? :)

Jag har spånat lite på tekniker man kan använda (jag tar gärna emot förslag på fler, samt fler åsikter kring dem) samt hur man använder tekniken...

TEKNIK 1: Helt (100%) skilda filer (flera webbplatser)
FÖRDELAR
Du kan ha helt olika upplägg på de olika webbplatserna utan att behöva designa till fördel för ett visst sprk.

NACKDELAR
Det finns risk för en del dubbelarbete för kod som annars skulle vara gemensam.


TEKNIK 2: All content är dynamisk och läses in från db (t.ex. INDEX,SV och INDEX,EN)
Förtydligande: Denna teknik används ju även för att t.ex. få fram nyheter och blogginlägg på rätt språk... (select * from blogg where lang='en')
FÖRDELAR
Bara en webbplats om man ser det till filstruktur.

NACKDELAR
Denna teknik fungerar bra för content, men inte för materialet utanför (t.ex. om man har en meny som behöver översättas). Därför bör den kombineras med exempelvis teknik 3.

TEKNIK 3: Anropa texter via konstanter - som man byter ut dynamiskt
Exempel: T.ex. ha en sv.php och en.php med en massa konstanter i stil med define("MAIN_MENU", "Huvudmeny").

FÖRDELAR
Det fungerar bra för enskilda ord och korta texter
Ganska smidigt med alla ord samlade i en fil (den typiska fördelen med konstanter)

NACKDELAR
Fungerar inte speciellt bra på content, det blir lite för massivt.
Fungerar i allmänhet bara bra på statiskt material, så den måste kombinerad med annan teknik.

TEKNIK 4: Ifsatser i varje php-fil som skriver ut material enligt språkval
Exempel:

if($lang == "en")
echo("Welcome to my site");
else if($lang == "sv")
echo("Välkommen till min webbplats");
else ......

FÖRDELAR
Du har content på alla språk i rätt fil. Det är lätt att hålla ordning och översikten tenderar att bli bra.

NACKDELAR
Fungerar ju förståss bara bra för statisk content


SLUTSATS
Efter att ha klurat i ett par timmar så är det väl ovanstående tekniker som gäller för en flerspråkig site. Antingen alla tillammans eller några av dem (alternativt ettan enskilt, men det känns orealistiskt för en stor dynamisk site).

Är det någon som känner sig riktigt bra på att ta fram flerspråkiga siter som kan presentera en metod som verkligen känns bekväm att jobba med, både i stora och medelstora projekt.

Jag själv är inne på att använda teknik 2 för nyheter, artiklar och andra element som hämtas dynamiskt.
Använda teknik 3 för enskilda och korta texter, t.ex. huvudrubrik, menyrubrik etc.

Sist men inte minst använda teknik 4 på statisk content.
Just nu ser min struktur ut såhär inuti en php-fil (exempel):

-foretaget.php- (tar get-parameter för nästa nivå)

if($param == "foretagshistoria")
{
echo("all text om företagets historia");
}
else if($param == "personal")
{
echo("all text om personalen");
}

Och om man nu kombinerar det där med teknik 4 så får man alltså duplicera alla ifsatser och anpassa dem efter språk. Eventuellt sätter man dessa ifsatser inuti en if($lang == "sv") och sedan kommer en för engelska, och alla ifsatser på nytt. Alternativt blandar man, så att varje text ligger tillsammans med sina översättningar, det kanske är smidigast att arbeta med.


Sååå, är det någon som har några spännande förslag och erfarenheter att dela med sig av?

Onkelborg 2007-10-09 16:29

Citat:

Originally posted by totoo@Oct 9 2007, 14:56
Jag har gjort flerspråkiga siter förr, men jag har aldrig kommit fram till någon bra struktur.
Finns det överhuvudtaget någon klockren lösning för flerspråkiga siter?

Har inte enorm erfarenhet, men jag har pysslat med det, och läst rätt mycket i alla fall :)

1) Innehåll: _Alltid_ i databas/annan lagring skiljd från presentation (ex. xml-fil, även om databas är _mycket_ bättre att söka i.) Cache skadar inte, även om man kanske får vara måttlig när det gäller vad man ska cacha, och hur länge
2) Gemensamt: Antingen i resource-filer, eller i databas. (Cacha särskilt det sistnämnda, men helst resource-filer också, om man nu inte gör den, enligt mig, lite småfula metoden att deklarera variabler för allting. En hashtable är nog lämpligare, grötar inte ner så mycket)

Av det du funderat igenom så tycker jag att man ska undvika 1:an och 4:an. 3:an om det enbart används till gemensamt, samt med modifikation så att man har en stor array eller något liknande istället för en stor arsenal variabler.

Vidare, en bra idé kan vara att skapa wrapperfunktioner runt allting, på så sätt kan man enkelt göra fallbacks om t.ex. en text saknas i ett språk, då kan man ta till texten för något annat språk (och ev. rapportera om felet?) så att man åtminstone slipper runtimeerrors och annat knepigt (en, av många, anledningar till att inte deklarera en hop med variabler)

mbomelin 2007-10-09 17:14

Det finns nog inte någon klockren lösning tyvärr.

Teknik 1 är bra i de fall det är skillnad i strukturen mellan språken.

Teknik 2 funkar bra om alla språk har samma struktur, och till saker som t.ex. nyheter, produkter osv.

Teknik 3 är alltid bra till knappar, beskrivande texter för formulärfält osv.

Teknik 4 har jag aldrig använt då jag inte arbetar med statiskt innehåll.

grazzy 2007-10-09 17:19

Edit: insåg att jag missförstod frågeställningen lite. Hursomhelst så är gettext ett bra alternativ för dig.


Ett sätt att lösa det här på (inte bara flerspråkighet utan även många siter med samma kodbas) är följande:

-En orginalkatalog med din källkod.
-Källkoden använder gettext (gettext är unix inbyggda stöd för just språkhanternig) för lokala förändringar per site och språkmässiga skillnader.
-Varje site är en egen katalog med symlänkar till alla filer i orginal-katalogen med undantaget för gettexts locale-katalog (detta gör att du har en egen uppsättning med språket för varje site, här kan du tex definera keywords som "database_name" så att olika siter jobbar mot olika databaser).

En fördel är att om du vill göra en lokal förändring på en specifik site utan att behöva ändra alla siter är att du bara kan ta bort symlänken till tex "information.php" och på det sättet redigera den helt utanför de andra siterna. Detta bidrar förstås på sikt till jobbiga nackdelar iom att du skapar flera versioner av filen.

Det är inga problem att göra så att en eller flera siter har flera språk iom att du kan definera din meny via gettext och på det sättet lägga till förändring av språk (detta skapar såklart en ny dimension som jag inte har jobbat med .. många siter, många språk; fast det borde inte vara några problem).

Ytterligare fördelar är att alla ändringar du gör i din orginal-mapp går direkt ut på alla siterna...

Det här systemet använder vi tex på våra hotell-siter och det fungerar alldeles utmärkt.

Oavsett om du tycker det här är en passande lösning så borde du definitivt titta på gettext. Det är den bästa lösningen för unix-plattformar.

orreborre 2007-10-09 17:24

Jag gör så att jag skapar en xml-fil för varje språk, t.ex.
<locale lang="se">
<menu>
<home>Hem</home>
....
</menu>
<headers>
<index_header>Välkommen till min sida</index_header>
...
</headers>
</locale>

Vidare lagrar jag i databasen vilka språk som finns tillgängliga samt vilket som är default och vilket prefix/dir språkfilen har.

När en sida anropas kontrolleras först om användaren skicka med en GET-var för att byta språk, sedan om det finns en sessions-var för språk, sedan om det finns en språk-cookie satt. Finns inget av dessa väljs det språk som är default i databasen.

Sedan hämtar php rätt språkfil, gör om denna till ett objekt.

Där man sedan vill ha någon sträng på sin sida anropar man språkobjektet:
print $LANG->menu->home;

Det som är smidigt med xml-filer är att man lätt kan skicka över det till någon som ska översätta ett språk + att man bryter ut det från php-kod.

totoo 2007-10-09 18:06

Citat:

Originally posted by Onkelborg@Oct 9 2007, 16:29

Har inte enorm erfarenhet, men jag har pysslat med det, och läst rätt mycket i alla fall
1) Innehåll: _Alltid_ i databas/annan lagring skiljd från presentation

Varför då? När jag har statiskt material så lagrar jag det också statiskt så att säga. Jag separerar aldrig avsiktligt informationen på det sättet du föreslår. Så gör jag bara om det av naturliga skäl inte går att lagra det statiskt (t.ex. nyheter, blogg, forum etc som är dynamiskt matade).

Edit: Nu förutsatte jag att du menade överhuvudtaget när man gör webbplatser, men om du menade just för flerspråkksiter så hänger jag med.

mr_lundis 2007-10-09 20:06

Citat:

Ursprungligen postat av totoo
Citat:

Ursprungligen postat av Onkelborg
Har inte enorm erfarenhet, men jag har pysslat med det, och läst rätt mycket i alla fall
1) Innehåll: _Alltid_ i databas/annan lagring skiljd från presentation

Varför då? När jag har statiskt material så lagrar jag det också statiskt så att säga. Jag separerar aldrig avsiktligt informationen på det sättet du föreslår. Så gör jag bara om det av naturliga skäl inte går att lagra det statiskt (t.ex. nyheter, blogg, forum etc som är dynamiskt matade).
Edit: Nu förutsatte jag att du menade överhuvudtaget när man gör webbplatser, men om du menade just för flerspråkksiter så hänger jag med.

Att separera innehåll och presentation är ett måste, speciellt på stora sidor.

Säg att du en dag vill göra lite ändringar i din layout på sidan, som kräver att du editerar dina filer, inte bara css-mallen. Då måste du ju gå igenom *alla* dina statiska sidor och ändra. Har du en separat presentations-mall behöver du bara ändra i den.

totoo 2007-10-09 20:30

Citat:

Originally posted by mr_lundis@Oct 9 2007, 20:06
Att separera innehåll och presentation är ett måste, speciellt på stora sidor.

Säg att du en dag vill göra lite ändringar i din layout på sidan, som kräver att du editerar dina filer, inte bara css-mallen. Då måste du ju gå igenom *alla* dina statiska sidor och ändra. Har du en separat presentations-mall behöver du bara ändra i den.

Ja, alltså... Man inkluderar ju huvud och fot (och vad man nu mer behöver) från respektive sida som löser det problemet i 99 fall av 100. Men jag antar att det inte var så han menade från början.

Jag har ingen design i mina php-filer som innehåller content, men det Onkelborg talade om är ju att ta det ännu längre bort, t.ex. ända ut till databasen...

martine 2007-10-10 01:24

Min lösning (som jag tycker fungerar rätt bra) är att:
1. Använda xml-filer för all statiskt innehåll på sidan, menyer, bakåtknappar, felmeddelanden och
2. Databas språksorterad för dynamiskt innehåll som t.ex. nyheter, artiklar, etc.

Självklart beror det lite på applikationen eller sidan hur man lägger upp det men en enkel lösning är t.ex.
Kod:

<rubrik>
 <sv>Hej</sv>
 <en>Hello</en>
</rubrik>

då räcker de med att använda t.ex. $xml->rubrik->$lang för att konsekvent sätta språket på alla sidor om man sätter $lang till språket. Databasen kan exempelvis se ut som (med psuedo-sql)
Kod:

CREATE TABLE nyhet (
id INT,
sv VARCHAR,
en VARCHAR
)

så att man även här kan använda $lang.

Därmed blir språken skalbara (ta bort och lägga till språk kan t.o.m. då enkelt skötas via ett CMS för ändamålet) och att kontrollera att det är ordning på språken är rätt enkelt. Alltså i princip Teknik 2 tillsammans med en Teknik 5, dvs. xml för relativt statiskt innehåll.

Den sämsta lösningen är naturligvis att använda if-loopar med hårdkodad text. Blir enormt oöverskådligt och svårt att handera.

Onkelborg 2007-10-10 01:49

Citat:

Ursprungligen postat av totoo
Citat:

Ursprungligen postat av Onkelborg
Har inte enorm erfarenhet, men jag har pysslat med det, och läst rätt mycket i alla fall
1) Innehåll: _Alltid_ i databas/annan lagring skiljd från presentation

Varför då? När jag har statiskt material så lagrar jag det också statiskt så att säga. Jag separerar aldrig avsiktligt informationen på det sättet du föreslår. Så gör jag bara om det av naturliga skäl inte går att lagra det statiskt (t.ex. nyheter, blogg, forum etc som är dynamiskt matade).
Edit: Nu förutsatte jag att du menade överhuvudtaget när man gör webbplatser, men om du menade just för flerspråkksiter så hänger jag med.

Jag pratar bara om lokaliserad siter, kopior av kod vill man _aldrig_ ha att göra med, av den anledning vill man inte ha två fysiska filer med samma innehåll på två olika språk; vill man ändra någonting i layouten/koden så har man två ställen att ändra på. Vidare, använder alltid mallar i någon form (utöver css alltså.) Du kan utgå ifrån att om du vill ändra en sak så ska du bara behöva ändra den på ett ställe, behöver du ändra på fler ställen så har du troligtvis gjort något galet (behöver inte gälla jämt, men..)

(Ska kanske lägga till att mina personliga hemsidor är inget jag driver särskilt seriöst, bloggen är svensk rakt igenom, utom lite texter som är engelsk (blogger..) bara för att jag inte orkat ändra mallen, och min vanliga är, tja.. en enda html-sida med lite tråkig text..)

totoo 2007-10-10 07:53

Onkelborg Okej, då förstår jag vad du menar. Men det är inget problem jag har, för jag är noga med att ha mallar för allt, så jag behöver aldrig ändra på två ställen, sådana nybörjarmisstag gör jag inte efter alla år. :)

martine satte absolut huvudet på spiken! Det där var absolut en snygg lösning, snyggare än vad jag trodde fanns! :) TACK!

Däremot känns det i min värld smidigare att t.ex. nyheterna har ett enskilt objekt i databasen per språk.
Inte att tabellen har fält för varje språk, utan att tabellen ser ut mer såhär

CREATE TABLE nyhet (
id INT,
subject VARCHAR,
lang VARCHAR,
text VARCHAR
)

sedan kör man query i stil med select * from nyhet where lang=$lang - eller var det så du menade? Det känns ju "mer skalbart" (smidigare) att göra så då man slipper skapa nya fält för varje språk.

Nu till en parantes, vad är det för xml-lib ni använder för att få en sån där fin objekthierarki? $rot->barn->barn->wheeo ??

Jag har aldrig parsat xml i just php, så jag tänkte höra om ni använder något vettigt istället för phps inbyggda som känns rörig (jag är van med olika libs från c++ som är rätt rena, typ tinyxml).

tartareandesire 2007-10-10 11:24

Tycker personligen varianten med variabler i separata språkfiler är att föredra då det blir smidigare om möjligheten finns att man senare ska låta andra personer översätta till ytterligare språk. Det blir lättare att se alla ord än i en xml-fil tycker jag. Inget hindrar förstås att man konverterar xml-filer just för detta ändamål men det innebär ju merarbete.

Daniel.st 2007-10-10 11:31

Använd en sida som "master". Varje ytterligare språk är skilda i filer/dbn men har en lösare kopplad relation till mastern för att kunna hålla ihop sidorna i navigeringen osv. Om antalet sidor osv. inte är samma i alla variationer och mastern har man bara relationer till mastern i det fall det går att skapa en logisk sådan.

allstars 2007-10-10 11:32

Citat:

Originally posted by martine@Oct 10 2007, 01:24
Min lösning (som jag tycker fungerar rätt bra) är att:
1. Använda xml-filer för all statiskt innehåll på sidan, menyer, bakåtknappar, felmeddelanden och
2. Databas språksorterad för dynamiskt innehåll som t.ex. nyheter, artiklar, etc.

Självklart beror det lite på applikationen eller sidan hur man lägger upp det men en enkel lösning är t.ex.
Kod:

<rubrik>
 <sv>Hej</sv>
 <en>Hello</en>
</rubrik>

då räcker de med att använda t.ex. $xml->rubrik->$lang för att konsekvent sätta språket på alla sidor om man sätter $lang till språket. Databasen kan exempelvis se ut som (med psuedo-sql)[CODE]

Jag är lite nyfiken på hur jag anropar xml-noderna från klassisk ASP till sidan.

Jag hade från början tänkt att använda teknik 2 & 3 tillsammans. Det gjorde jag för en site jag gjorde åt en kund i våras, men det blev lite rörigt med alla statiska meddelanden då jag hade lite ostruktur i språkfilen.
Jag skall snart påbörja en flerspråkig sajt, så det är alltid intressant att få tips.

martine 2007-10-10 13:29

Citat:

Originally posted by totoo@Oct 10 2007, 07:53
martine satte absolut huvudet på spiken! Det där var absolut en snygg lösning, snyggare än vad jag trodde fanns! :) TACK!

Däremot känns det i min värld smidigare att t.ex. nyheterna har ett enskilt objekt i databasen per språk.
Inte att tabellen har fält för varje språk, utan att tabellen ser ut mer såhär



Jag har aldrig parsat xml i just php, så jag tänkte höra om ni använder något vettigt istället för phps inbyggda som känns rörig (jag är van med olika libs från c++ som är rätt rena, typ tinyxml).

Hur du exakt lägger upp databasen beror förstås på vad du har för material, om alla nyheter alltid översätts till alla språk eller om olika nyheter finns på olika språk osv. Det gäller som vanligt att ha en välstrukturerad (normerad) databas utan redundanta fält.

I php:
Kod:

$xml = simplexml_load_file('meny.xml');
echo $xml->meny1->rad3->$lang

för att dynamiskt kunna förändra menyn så använder du foreach för att loopa igenom och skriva ut hela menyn t.ex. Titta på phps simplexml-funktioner (php5).

Onkelborg 2007-10-10 13:35

Citat:

Originally posted by martine@Oct 10 2007, 13:29

Hur du exakt lägger upp databasen beror förstås på vad du har för material, om alla nyheter alltid översätts till alla språk eller om olika nyheter finns på olika språk osv. Det gäller som vanligt att ha en välstrukturerad (normerad) databas utan redundanta fält.

Hm.. Man borde rimligtvis inte ha en kolumn för varje språk någonsin :/

Förslagsvis har man språk, land, en nyckel samt själva texten. språk är helt enkelt språk, land är inte helt fel att ha (t.ex. du kan ha svensk sida, men viss information skiljer sig beroende på om besökaren är bosatt i sverige eller finland.. Eller engelskan, viss information kan mycket väl vara specifik för usa, annan för uk.) Man kan land-kolumnen tom som standard. Nyckeln är någon form av nyckel för vad det är för text bara

anders.n 2007-10-11 10:06

För php gillar jag Smarty Template Engine (smarty.php.net). Då kan man helt skilja kod från layout.

Man skapar en template-mapp som innehåller designen, och kan t.ex. ha olika template-mappar för olika språk.

Sedan läser man in sidinnehåll från en databas (eller direkt från filer om man så vill), och använder Smarty för att "rita ut sidan". Man kan även använda dess cache-funktioner, och loopar på sidan, etc.

t.ex /templates/main_page.tpl
Kod:

<html>
<head><title>{$title}</title></head>
<body>{include file='left_menu.tpl'}

{$body_content}

</body></html>

sedan... website.php
Kod:

$language = 'english';
if (isset($_GET['language'])) $language=mysql_real_escape_string($_GET['language']);

// Kolla om den finns i cache... cache_id är per språk.
if (!$smarty->is_cached('main_page.tol', $language))
{ // Finns inte i cache, läs in från databasen...
  $title = read_from_database('index_sida', 'title', $language);
  $content = read_from_database('index_sida', 'content', $language);

  // Sätt värden i Smarty-template
  $smarty->assign('title', $title);
  $smarty->assign('body_content', $content);
}

// Sätt cache till... 24 timmar... (så att den bara behöver ansluta till databasen en gång om dagen för sidan)
$smarty->cache_lifetime = 60 * 60 * 24;

// Visa sidan... antingen från cache eller nyhämtat från databas om den inte var cachad...
$smarty->display('main_page.tpl', $language);

(sådär skulle jag inte koda, och man ska inte ha ofiltrerad input som cache_id, språk som id i databasen, och kunna falla tillbaka till engelska, men.. ;P)

Det jag gillar är att man enkelt kan loopa igenom arrayer och hantera associativa arrayer i templaten, och ha enkel ...

Man kan hämta t.ex. en medlemslista från databasen som en array av associativa arrayer... sedan loopa igenom dem, och i templaten ha typ:

Kod:

<h1>Lista</h1>
{section name=i loop=$users}
<p>Namn: {$users[i].namn}<br />
Ålder: {$users[i].alder}<br /></p>
{sectionelse}
Finns inga! Tom array!
{/section}

om man skickar den en array som innehåller [ [name => 'kalle', alder=5], [name => 'olle', alder=7 ] (vilket ENKELT kan hämtas direkt från databasen), så får man följande output:

Kod:

<p>Namn: kalle<br />
Ålder: 5<br /></p>
<p>Namn: olle<br />
Ålder: 7<br /></p>

Sedan kan man ju med hjälp av mod_rewrite och/eller path_info få "snygga" URLer:
www.example.com/english/nice_page_name

Finns naturligtvis många andra befintliga template-klasser för olika språk, men för php har jag av någon anledning fastnat för Smarty. :)

Magnus_A 2007-10-11 11:59

Oavsett hur man struktuerar sin språkhantering så bör man nog tänka på administrationen så man får en bra överblick över vilka ord/textbitar som motsvarar varandra på respektive språk.
Antar att du har ett "master"-språk och att alla versioner av sajten är översättningar från detta master-språk. Om du då byter text/funktion på knappen "Framåt" till "Bakåt" så måste du kunna överblicka och verifiera att denna ändring översätts och genomförs i alla språkfiler/tabeller/fält.

danjel 2007-10-15 17:01

Som jag planerar att införa på en site är det helt databas drivet,
kom fram till att det bästa för vår situation var ett admingränsnitt där man kan gå in och ändra språken.
Tanken är en admin kan skapa ett "textobjekt", det kan vara en sida eller en meny eller ett mailutskick m.m
Sen kan han skapa ett eller flera "text id " till det objektet..
För varje "text id " kan man sen lägga in en olika översättningar/språk.

Om sedan ett text id heter "header" för en viss sida får man fram rätt språk
genom att anropa en funktion :
Translate("header")

(Det sker ett db anrop per text objekt)


Alla tider är GMT +2. Klockan är nu 16:00.

Programvara från: vBulletin® Version 3.8.2
Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
Svensk översättning av: Anders Pettersson