Making WeWork’s Global Voice Local 🌎🌍🌏 #g11n #wearewework #teamsummit (at WeWork) https://www.instagram.com/p/B7KUkFNBtz1/?igshid=aln7av9r4imq
seen from Italy
seen from United States

seen from China
seen from Canada
seen from United States

seen from United States
seen from United States

seen from United States
seen from United States

seen from United States
seen from China

seen from United Kingdom
seen from United States
seen from China

seen from Guinea
seen from Yemen

seen from Italy
seen from Belarus

seen from Italy
seen from Colombia
Making WeWork’s Global Voice Local 🌎🌍🌏 #g11n #wearewework #teamsummit (at WeWork) https://www.instagram.com/p/B7KUkFNBtz1/?igshid=aln7av9r4imq
Most of us are just used to seeing the glamorous and heroic genius wins of the Kenyan athletes but do not have even a glimpse of what it takes. As Albert Einstein once said Genius is 99% perspiration and 1% inspiration. Generally, human beings have an immense potential if blood, sweat and heart is invested in whatever endeavors they engage in. That is exactly what the Kenyan athletes undergoes. So, as you celebrate them today especially at the #IAAF2017 competition, do not just ask why but also how? What immense potential do you have? What are you doing about it? When can we start celebrating you also? For all your English to Swahili Games and Sports translations, look no further. #SwahiliTranslation #SwahiliTranslator #SomaliTranslation #SomaliTranslator #AmharicTranslator #TwiTranslator #TigrinyaTranslator #l10n #i18n #g11n. Being a qualified and experienced #translator, among many other English-to-Swahili translators on Upwork, I can help you ensure your cross-cultural communications in games and sports go smoothly. I will be delighted to be your preferred English to Swahili translation expert. #xl8, #t9n I also have a Team of in-house resources, #TeamLanguagesAfrica, who can handle Games and Sports translation in ALL the other popular and rare #AfricanLanguages.
Giving You More To Smile About. Meeting all your Turkish language needs. @Turklingua #turkish #translation #l10n #xl8 #t9n #g11n #linguistics #i8n #businesstranslation #technicaltranslation #documenttranslation #financialtranslation #legaltranslation #turkishenglish #turkishtranslation #englishturkish #Indianapolis #Pittsburgh #Phoenix #Orlando #Oakland (at United States)
Affordable and Reliable Turkish Translation Services. Giving you 24/7 Access to Turkish Translation Professionals. @Turklingua #turkish #translation #l10n #xl8 #t9n #g11n #linguistics #i8n #businesstranslation #technicaltranslation #documenttranslation #financialtranslation #legaltranslation #turkishenglish #turkishtranslation #englishturkish #NewYorkCity #Washington #SanFrancisco #LosAngeles #Seattle (at United States)
Software Global-what?
What is Software Globalization by the way? Why is this important, and why should I even care if my software works in Zanzabar? Software is no longer an isolated entity living only in English speaking countries, software must be world ready from day one. Day one being the inception of the original thoughts about a product line, or you will be missing out on huge revenue opportunities. As the…
View On WordPress
Welcome to Globalization United
Welcome to Globalization United
Hello dear readers and welcome to Globalization United, a website dedicated to the implementation, practices, and challenges of testing Global Web Sites. The site is dedicated to practices and praticioners of this closed and some times lonely field. What is the purpose of this site, rather than just that heady statement? The site is dedicated to: individuals whom are currently practicing…
View On WordPress
AngularJS İle Çoklu Dil İçeren Uygulamalar Geliştirmek
İki hafta önce AngularJs Bootcamp de bu konu hakkında bir sunumum vardı. Sunumda sahnenin verdiği heyecandan dolayı atladığım şeyler olmuştur diye bu konuyu bir blog yazısında toplamanın iyi olabiliceğini düşündüm.
Konuya başlamadan önce bootcamp hakkındaki düşüncelerimi belirtmek istiyorum. Organizasyon sorunsuz ve sıfır aksama ile tamamlandı. Sunumlar arası oluşan aksamanın hiç olmadığı nadir etkinliklerden biri. 2 gün süren dolu dolu bir etkinlikti diyebilirim. Umarım böyle etkinliklerin sayısı gittikçe artar.
Gelelim konumuza;
internationalization (Uluslararasılaştırma) Nedir ? Tek sistemde birden fazla dil desteği vermeyi genel olarak Türkçe karşılığı uluslararasılaştırmak olan internationalization terimi ile adlandırıyorlar. Söylenmesi bile zor olan ve baya uzun olan bu kelimeyi i18n olarak kısaltmışlar. (i + 18 harf + n)
Localization (Yerelleştirme) Nedir ? Sorunumuz sadece bir sistemde dili çevirmekle bitmiyor. Tarih, zaman, para birimi, ısı birimleri ve bu tarz şeyleri de dille göre çevirilmesi gerekiyor. Bu işin kapsamı da Türkçe karşılığı yerelleştirmek olan Localization içinde yer alıyor. i18n gibi Localization kelimesini de l10n şeklinde kısaltmışlar.
Bu iki durumu da tamamladığımıza ürünümüz küreselleşmiş oluyor. Bu kavrama da Globalization diyorlar.
Dil Paketlerini isimlendirmek Sistemimizde birden fazla dil var. Her şey iyi güzel. Fakat dillerin birbirinden kolay ayırt edilebilmesi için bu isimlendirmenin belli bir standarta göre olması gerekiyor. Standarta uymanın artılarından biri ise herkes tarafından kabul görmüş ürünlerden dil bilgisi aldığınızda yine bu standart da olacağıdır. Örneğin kullanıcı ilk defa siteye girdiğinde kullandığı tarayıcının dilini varsayılan olarak gelmesini istiyorsunuz. navigator.language ile bu bilgiye eriştiniz. Kendi dilleriniz ile eşleştirmeniz gerekiyor. Eğer isimlendirmeniz bu standart da değil ise başlıyorsunuz ifleri yazmaya. Bu gibi sebeplerden dolayı kabul görmüş standartları kullanmak bence her zaman bir artısı vardır.
İsimlendirmeler Ülke + Bölge şeklinde yapılıyor. Örnek isimlendirmeler:
en_US (English US)
en_GB (English UK)
tr_TR (Türkiye)
Bu zamana kadar bu işleri nasıl yapıyorduk ? Herhangi bir Backend dilinin kullandığı template engine yardımı ile render ediyorduk. Örneğin gettext çok kullanılıyor. Bu şekilde herşey güllük gülistanlık gidiyorken neden client tarafında bu işlemi yapayım kı diyenleriniz oluyordur muhakkak. Burada da işin içine SPA lar (single page app.) giriyor. Sayfalar arası geçiş sayfa yüklenmeden yapılıyorken neden sadece dil değişimi için sayfayı yükleyelim ki. Sayfayı yenilediğimizde hem sayfanın tekrardan yüklenmesi hemde yüklendiği ara sizin client tarafında cachelediğiniz verinin gitmesi demek oluyor. Ekstra olarak bu tek sayfa uygulamayı geliştiriyorken bir framework kullanıyorsanız ve templatelerinizi farklı sayfalara parçaladıysanız o template leri render ederken de yine backend den render etmeniz gerekicek. Gittikçe karmaşık bir hale gidiyor.
Client tarafında çözüm üretmek ne kazandırıcak ? - SPA larda anlık dil değişimi. - Anlık oluşan olaylar kullanıcılar üzerinde bence güzel bir hissiyat bırakıyor. - Eğer işin fantezisine girerseniz şöyle bir şeyde yapabilirsiniz. Çeviri dosyalarınızı Firebase, Parse veya kendi yazdığınız bir WebSocket den serve ederseniz dil dosyasında herhangi bir değişim olduğu anda kullanıcı sayfayı yenilemeden onun ekranında bu işlemi yansıtabilirsiniz. - PO veya MO gibi uzantılar yerine JSON gibi temiz, okunaklı bir format da tutmuş oluyorsunuz. (Client de çözüm üretince illa bir JSON dosyasında tutacağınız anlamına da gelmiyor. Çeviri dosyalarını bir servisten de çekebilirsiniz. Bu gibi durumlar genelde sistem sahibinin kendi yönetim panelinden yeni dil ekleme çıkartma yapması durumlarında oluşuyor.)
AngularJS ile bir bakış. AngularJs ile Javascript kodundan çeviri işlemlerini oldukça başarılı bir şekilde ayırabiliyoruz. Aynı zamanda tarih zaman gibi şeylerin dille göre çevirimi çok pratik. Fakat AngularJS içinde dile göre içerik değişimi hakkında bir desteği yok. Ya bunu kendiniz yazmanız lazım yada bir paket tercih etmeniz lazım.
AngularJS tarih, zaman, para birimi gibi işlemleri dille göre çevirim yapan kısmı core kodundan ayrılmış durumda. Varsayılan olarak sadece ingilizce dile destek veriyor. Diğer diller için kullanmak istiyorsanız bower veya npm gibi bir paket yönetici ile bu paketi kurmanız gerekiyor.
$ bower install angular-i18n
Para Birimi, Tarih Çevirimleri
https://gist.github.com/bahattincinic/437e5b267ef2749d37d2
Kullanımı bu kadar basit. Sadece kullandığımız verinin tipini AngularJs e söylememiz yetiyor.
AngularJS deki Popüler İ18N Paketleri - github.com/rubenv/angular-gettext - github.com/angular-translate/angular-translate
i18n için bence en güzel AngularJS paketi diyebilirim. Çok esnek olması ve özelleştirilebilir olması ise en büyük artısı. Bu paketi geliştiren Pascal Precht yakın bir zamanda düzenlenen JSist konferansında sunum da yapmıştı.
Kurulum için:
$ bower install angular-translate
Basit bir örnek uygulama yapalım;
https://gist.github.com/bahattincinic/75ecfc470e136400dacf
Yukarıdaki örneği biraz inceleyelim. $translateProvider angular-translate paketi ile gelen özellikleri özelleştirebilmemizi sağlıyor. Örnekte çevirileri direk kod içerisinde olduğunu görüyoruz. key ve o keye karsılık gelen value lar şeklinde. angular-translate varsayılan olarak bu şekilde çalışıyor. Fakat size bunun dışında 3 tane daha yöntem sunuyor. Bunları da paketler haline getirmişler. Bu yöntemler şunlar;
- Çeviri içeriklerini apiden çekmek:
$ bower install angular-translate-loader-url
https://gist.github.com/bahattincinic/5105603a411f34c269f7
- Çeviri içeriklerini statik olarak dosyada tutmak:
$ bower install angular-translate-loader-static-files
https://gist.github.com/bahattincinic/6f075931584243c9fecc
- Çeviri içeriklerini parçalı tutmak (Her dili tek dosyada tutmak yerine mesela bunları modüllere göre parçalamak):
$ bower install angular-translate-loader-partial
https://gist.github.com/bahattincinic/dbae67fe0c5437676069
Sunduğu yöntemler bunlar. Bunların dışında kendinize özel bir şeyler yazmanıza da imkan tanıyor. Örneğin biz çeviri içeriklerimizi firebase de tutmak istiyoruz. Bununla ilgili küçük bir örnek yapalım.
https://gist.github.com/bahattincinic/077ea9e23557ae2bc57a
Örneğimizi incelemeye kaldığımız yerden devam edelim. preferredLanguage methodu eğer kullanıcı tarafından hiçbir dil seçilmemiş ise varsayılan dil atamada kullanılıyor.
Seçilen dili daha sonra hatırlanması için angular-translate bize 2 yöntem sunuyor.
Cookie de saklamak:
$ bower install angular-translate-storage-cookie
https://gist.github.com/bahattincinic/4b60c277ad08c2a5efea
localStorage da saklamak:
$ bower install bower install angular-translate-storage-local
https://gist.github.com/bahattincinic/176489785c1750601e8f
Bunların dışında özel olarak kendiniz de bir şeyler yazabiliyorsunuz. Örneği incelemeye kaldığımız yerden tekrardan devam :)
Javascript tarafında dil içeriklerimizi çektik dilin hatırlanmasını yaptık. Şimdi ise bu dil çevirisi içeriklerini template tarafında kullanalım
https://gist.github.com/bahattincinic/935440525c72e1a8531e
Her zaman template de çeviri yapmak sorunumuzu çözmeyebiliyor. Javascript tarafında kullanıcının yaptığı bir işlem sonrasında vermemiz gereken uyarıyı da çevirmemiz lazım.
https://gist.github.com/bahattincinic/d700cfb4ebe0feb738ee
Dil Değiştirmek:
Dil değiştirmek için $translate servisinin use fonksiyonunu kullanıyoruz. ($translate.use()) Bu fonksiyona parametre vermezsek aktif olan dili bize veriyor. Değer verirsek o değeri eskisi ile değiştiriyor.
https://gist.github.com/bahattincinic/da5891bea0ec8de37815
$locale değişimi
İçeriklerimizi çevirdik. Dil değiştirdiğimiz zaman tarih, zaman, para birimi gibi şeylerin değişmediğini gördük. Burada şöyle bir problem çıkıyor. AngularJS dinamik olarak $locale değişimine bir destek vermiyor. Dil değiştiği zaman o anda dile ait locale js dosyasını yükleyerek genelde çözüm buluyorlar. Bu işlemi yapan güzel bir paket var.
$bower install angular-dynamic-locale
https://gist.github.com/bahattincinic/da5891bea0ec8de37815
Örnek kod hakkında bahsedecek olursak, localeLocationPattern dil değiştiği anda ilgili dilin $locale içeriklerini nereden çekiceğinizi belirtmemize yarıyor. storeKey ise tuttuğu store daki (Cookie vs.) keyini temsil ediyor. useCookieStorage ise daha sonra hatırlaması için o anki dili cookie de tutmasını söylüyoruz. tmhDynamicLocale.set methodu ise locale değiştirmeye yarıyor.
Ek Not: - Buradaki para birimi çevirisi sadece sembolsel anlamda. Kur anlamında o paranın çevirilmesi sizin sorumluluğunuzda. - HTML5 form validation kullanıyorsanız verilen uyarılar tarayıcının diline göre veriliyor. Maalesef onu değiştiremiyorsunuz.
Sunumda yaptığım Demo: https://github.com/bahattincinic/angularjs-bootcamp
Sunum Linki: https://slides.com/bahattincinic/angularjs-ile-coklu-dil-destegi-veren-web-uygulamalari-gelistirmek/
İlgili Linkler
http://angular-translate.github.io/ https://github.com/lgalfaso/angular-dynamic-locale https://github.com/angular-translate/bower-angular-translate-storage-local https://github.com/angular-translate/bower-angular-translate-storage-cookie https://github.com/angular-translate/bower-angular-translate-loader-url https://github.com/angular-translate/bower-angular-translate-loader-static-files https://github.com/angular-translate/bower-angular-translate-loader-partial
Language Detection: A Witch's Brew?
photo by Arbron
Software developers sometimes have a tendency to cling to bits of ancient lore, even after they've long-since become irrelevant. Globalization, and specifically language detection, raises an interesting case-in-point. These days, language detection is really simple in most cases - just use the "Accept-Language" HTTP header, which pretty much every client on the planet passes to you. "But wait!" I hear you cry. "I thought the Accept-Language header wasn't to be trusted?" "Ancient and outdated lore, my friend" I will reply. "Ancient and outdated lore." It's true that the Accept-Language header has a troubled history. Because of this, many developers regard it the way medieval villagers might have regarded a woman with a warty nose and a pet cat - it should be shunned, avoided and possibly burned at the stake. In the early days of the web, Accept-Language really couldn't be trusted - many browsers made no real effort to send a meaningful value, often sending nothing (or worse, defaulting to requesting English) unless the user worked their way through a complicated configuration process buried 3 panes back in a labyrinthine dialog box. I'm rarely comfortable being categorical when talking about software engineering - there are usually too many variables, and too many specific circumstances for blanket assertions to be of use. But I can state with certainty that the "Accept-Language" header works these days, and any case where it doesn't can (and will) be considered an error on the part of the browser vendor. In two and a half years of running as an international site, we've only ever had one case where it didn't work. Helio, a cellphone company, had a browser which was custom-built for them in Korea, and had its "Accept-Language" header hard-coded to always request Korean, something which led to much confusion for the Flickr users amongst their American customers. When we alerted Helio to the problem, however, they were highly responsive - the next release of their software returned the correct value.
Location != Language
Perhaps driven by their superstitious fear of Accept-Language, many developers fall back on other means of determining their visitors' preferred language. Top of the list is IP-detection - pinpointing the visitor's current location using a lookup database. This isn't necessarily a terrible solution, but it's prone to a couple of problems. Firstly, even the best IP location databases contain mistakes, or outdated information where netblocks have been reassigned over time. Secondly, if you only rely on IP detection in order to provide language, travelers will often be highly confused when they reach their destination, connect to your site and are greeted with a language they don't speak. This can be especially disconcerting if you've been using a site regularly for years. This error is easily avoided, simply by applying a cookie the first time you pick a language for a user. By using a cookie, you can guarantee a consistent experience, regardless of where in the world a laptop happens to fly. None of this is to say that IP detection doesn't have its place. It's a useful fallback if you come across a user-agent that doesn't send Accept-Language, or you have a specific case where you believe you can't trust the header. But it general it should be just that - a fallback.
Always an option...
To guard against any possibility that you'll detect the wrong language for a user, it doesn't hurt to always provide language-switching as an option on every page. You'll see that we do that on Flickr (with the exception of Organizr)... You'll notice that we always render the language in its native name, so that people can find their preferred language, even if they understand nothing else on the page.
Rights and Wrongs
"But!" some of you will cry. "We are a site that deals with media content. There are rights issues and legal constraints - we have to send people in France to our French site"... ...which nicely brings me to the last point of this post. Many global sites will find themselves dealing with various jurisdictional concerns. There's no reason, however, that the "legal" logic in your code needs to be tied to the interface presentation. Whilst certain legal texts (Terms and Conditions, etc) can provide interesting challenges, if you keep presentation as an entirely separate consideration from jurisdiction, it's much easier to provide everyone with the best possible experience, regardless of where they are and what language they speak.
In Summary
All the above can be reduced to a very simple set of points to cut-out-and-keep for the next time you're asked to create a Global version of a website.
Use Accept-Language - it just works
Use IP detection as a fallback for language, or a separate test to determine jurisdiction
Cookie your visitors' language preferences, so you are consistent
Provide a simple way to switch language, everywhere
Treat language and compliance issues as two entirely separate problems
...at least, that's how we've been doing it on Flickr for two and a half years, and it's worked out pretty well for us so far.