PHP basit çeviri yaklaşımı - sizin fikriniz

7 Cevap php

Ben herhangi bir çerçeve kullanmadan, bir PHP web sitesi yapıyorum. Ben site birkaç dilde mevcut olduğunu gerekiyor ve ben bu konuda okuyor ve biraz kafa karıştırıcı gibi görünüyor. Orada çeşitli çözümler vardır ama hepsi belirli bir çerçeve bağlı gibi görünüyor.

Eğer aşağıda gösterildiği gibi basit bir çeviri fonksiyonunu kullanarak ne düşünüyorsun?

I mean, I would like to know what can be a disadvantage of using such code. Here it is (this is just a simple and incomplete sample):

class Translator{

    private $translations;

    public function __construct(){
        $this->translations = array(
            'Inbox'  => array(
                'en' => 'Inbox',
                'fr' => 'the french word for this'
            ),
            'Messages' => array(
                'en' => 'Messages',
                'fr' => 'the french word for this'
            )
            //And so on...
        );
    }

    public function translate($word,$lang){
        echo $this->translations[$word][$lang];
    }
}

7 Cevap

Bu kötü görünmüyor. Bunu birçok kez kullanılan gördüm.

Ancak dil başına bir dosyada farklı dizelerini ayırmak olacaktır. Dosyaları büyük olsun, en azından, ya da eğer, dil başına modül başına bir dosya.

(Eğer herhangi bir önbellek diğer sistemine güvenmek yoksa) Sonra çeviri sınıfı yeni bir dil kullanılacak her zaman dil dosyalarını yüklemek ve önbelleğe alabilir.

Ne demek istediğimi küçük bir örnek

class Translator {
    private $lang = array();
    private function findString($str,$lang) {
        if (array_key_exists($str, $this->lang[$lang])) {
            return $this->lang[$lang][$str];
        }
        return $str;
    }
    private function splitStrings($str) {
        return explode('=',trim($str));
    }
    public function __($str,$lang) {
        if (!array_key_exists($lang, $this->lang)) {
            if (file_exists($lang.'.txt')) {
                $strings = array_map(array($this,'splitStrings'),file($lang.'.txt'));
                foreach ($strings as $k => $v) {
                    $this->lang[$lang][$v[0]] = $v[1];
                }
                return $this->findString($str, $lang);
            }
            else {
                return $str;
            }
        }
        else {
            return $this->findString($str, $lang);
        }
    }
}

Bu arayacaktır. Dil bu gibi girdileri yaptıktan sonra adını txt dosyaları

Foo=FOO
Bar=BAR

Her zaman herhangi bir çeviri bulmak olmaması durumunda orijinal dize geri düşüyor.

Bu çok basit bir örnek. Ama daha büyük bir çerçeveye gerek var eğer kendiniz bunu yaparken benim görüşüme göre yanlış bir şey yok.

Her zaman bunu yapabilirsiniz çok daha basit bir şekilde kullanmak ve 'EN_Example.txt' adlı bir dosya oluşturmak için

class Example extends Translator {
    private $lang = 'EN';
    private $package = 'Example';
    public function __($str) {
        return parent::__($str, $this->lang . '_' . $this->package);
    }
}

Bazen değişkenleri içeren dizeleri çevirmek istiyoruz. Böyle bir yaklaşım, ben zaman zaman kullanmak kadar basit buldukları bu.

// Translate string "Fox=FOX %s %s"
$e = new Example();
// Translated string with substituted arguments
$s = printf($e->__('Fox'),'arg 1','arg 2');

Ayrıca printf işlevi bu gibi __() fonksiyonu içine konabilir değişken değişimi entegre

public function __() {
    if (func_num_args() < 1) {
        return false;
    }
    $args = func_get_args();
    $str = array_shift($args);
    if (count($args)) {
        return vsprintf(parent::__($str, $this->lang . '_' . $this->package),$args);
    }
    else {
        return parent::__($str, $this->lang . '_' . $this->package);
    }
}

Bunun için bir sınıf veya fonksiyonları kullanarak avantaj proje büyüdükçe dil depolama değiştirebilirsiniz olmasıdır. Yalnızca birkaç dizeleri varsa, çözümü ile herhangi bir sorun kesinlikle yoktur.

Eğer dizeleri bir sürü varsa tüm sayfa yükleri dil diziler yüklemek zaman, bellek ve sabitdisk kaynaklarını sürebilir. Sonra muhtemelen farklı dosyalara bölmek isteyen, ya da belki hatta bir veritabanı arayüzü kullanmaya. I veritabanı kullanıyorsanız, önbelleğe kullanmayı düşünün (örneğin, memcached) yani her sayfa yük kez veritabanı yüzlerce sorgulamak gerekmez.

Ayrıca gerçekten hızlı önderlemeli dil dosyalarını kullanır gettext hangi kontrol edebilirsiniz.

Bunu kabul değil görünen bir kaç şey vardır:

  • Sadece tek kelime çeviri mi? Ne cümle yapısı ve diller arasındaki farklılık sözdizimi hakkında?
  • Bir kelime ya da cümle henüz bir dile tercüme edilmemiştir zaman ne yaparsınız?
  • Lütfen çeviriler değişkenleri destekliyor mu? Bir cümledeki kelime sırası farklı dillerde farklı olabilir, ve bir değişken varsa o genellikle sadece cümlenin etrafında sözcüğü bölmek için yeterli olmayacaktır.

Ben kullandım ve PHP için tavsiye ederim bir iki çözüm vardır:

  • gettext - zamanda birden çok dilde desteklenen
  • intsmarty - Smarty şablonlara dayalı

Ben sadece bir her dil için eklemek kullanmak daha kolay olabilir sanırdım, içeriği sadece tanımlar bir liste olabilir.

Bunu yaparak, tüm dil veri ve düzenli olarak 'tercüme' işlevinin yükü dahil yükü hem önlemek istiyorum.

Sonra tekrar, bu yaklaşım gelecekte flexability açısından şeyleri sınırlamak olacaktır. (Bu olsa bir faktör olmayabilir.)

Bu bir çerçeve kullanmak değil iyi. Ben senin işlevi ile görmek tek sorun belleğe çok veri yüklüyor olmasıdır. Her dil, sadece kullanılan dil yüklemek gerekir bu şekilde diziler sahip öneriyoruz.

Sabitleri (tanımlar) kötü bir uygulama kullanıyor mu?

İşte ben bunu kurulum var nasıl. Bu sadece çoklu dil öğretimine destek oldu.

Ben bir Portekizli dosyası ve dolu bir ingilizce dosyaları var:

define('CONST','Meaning');

Belki bu biraz bir bellek domuz, ama ben istediğiniz her erişebilirsiniz :)

Ben bir oop yaklaşım değişebilir, ama şimdi ben bu var.

Ben böyle bir sorun (ama çok küçük bir site için, sadece birkaç sayfa) uzun zaman önce, ben adlı bir dosya oluşturdum langpack.php ve benim sitede herhangi bir metin dizesini vardı yoluyla çalıştırılacak vardı söyledi. Şimdi, benzer bir yaklaşım kullanmak, ancak birden çok dosya üzerinde bölünmüş olacaktır.

Example OOP Approach

langpack.php

abstract class langpack {
    public static $language = array();

    public static function get($n) {
        return isset(self::$language[$n]) ? self::$language[$n] : null;
    }
}

english.php

final class English extends langpack {
    public static $language = array(
        'inbox' => 'Inbox',
        'messages' => 'Messages',
        'downloadError' => 'There was an error downloading your files',
    );
}

french.php

final class French extends langpack {
    public static $language = array(
        'inbox' => 'Inbioux',
        'messages' => 'Omelette du Fromage',
        'downloadError' => 'C\'est la vie',
    );
}

Sen oradan fikir almalısınız. Config dosyasında bir autoloader uygulamak ve daha sonra dili yüklerken kolayca sınıf örnekleme, böyle bir şey ile birlikte PHP'nin değişken doğasını kullanarak, oturumda, URL veya ne olursa olsun yapabileceği bir şey olmalı:

$langpack = new $_SESSION['language'];
echo $langpack::get('inbox');

Tabii ki, tüm bu (yoluyla ele mutlak başvurular ile $GLOBALS), basit diziler ile yapılan ve bir zorunluluk tarzda erişilebilir olabilir bazı yükünü azaltmak ve hatta bu tüm biraz ele olduğu hangi mekanizmaları yapmak için daha şeffaf, ama hey, o, çok OO olur olmaz mıydı?