2009-09-12 33 views
23

Câu hỏi cập nhật thay vì làm một câu hỏi mới ...Cách hiệu quả nhất để làm tệp ngôn ngữ trong PHP là gì?

Tôi thực sự muốn cung cấp một vài ngôn ngữ khác thay thế sau đó bằng tiếng Anh trên trang web mạng xã hội của tôi Tôi đang xây dựng, điều này sẽ được lần đầu tiên tôi làm bất kỳ loại dịch ngôn ngữ vì vậy hãy chịu với tôi.
Tôi đang nghiên cứu vì vậy tôi là al tai và mở cho các ý tưởng và tôi có rất nhiều đã ở đây là những câu hỏi.

1)
Ý nghĩa của i18n, tôi thường thấy khi nghiên cứu dịch ngôn ngữ trên SO?

2)
Hầu hết mọi người nói sử dụng gettext PHP có một phần mở rộng hoặc hỗ trợ cho nó,
tôi cũng đã được nghiên cứu nó và tôi có một sự hiểu biết cơ bản của nó, như xa như tôi có thể nói đó là một nhiều công việc phụ để đi tuyến đường này,
Tôi muốn viết mã trang web của mình để sử dụng các chức năng của nó, nghĩa là; _ ('Xin chào thế giới bây giờ tôi đang nói tiếng Anh') hoặc người khác gettext ('xin chào thế giới tôi đang nói tiếng Anh') là không có vấn đề như bất kỳ tuyến đường tôi đi sẽ yêu cầu đó.
Nhưng sau đó bạn phải cài đặt gettext trên máy chủ của bạn và làm cho nó hoạt động,
sau đó sử dụng một số trình chỉnh sửa đặc biệt để tạo các tệp đặc biệt và biên dịch chúng tôi nghĩ?

Nghe như một cơn đau, tôi hiểu điều này được cho là tuyến đường tốt nhất để đi, mặc dù tất cả mọi người dường như nói nó là.
Vì vậy, ai đó có thể cho tôi biết tại sao đây là tuyến đường để đi?

3)
Tôi thực sự thích sự đơn giản của phương pháp này, chỉ cần xây dựng một mảng ngôn ngữ và kêu gọi các cụm từ bạn cần trong một chức năng giống như ví dụ dưới đây , sau đó bạn sẽ chỉ bao gồm một tập tin với ngôn ngữ thích hợp mảng.

Điều tôi thực sự muốn biết là, đây có phải là phương pháp hiệu suất kém hơn trên lưu lượng truy cập cao và trang web khá lớn so với sử dụng gettext hay không và liệu bạn có thể giải thích tại sao không?

<?PHP 
//Have seperate language files for each language I add, this would be english file 
function lang($phrase){ 
    static $lang = array(
     'NO_PHOTO' => 'No photo\'s available', 
     'NEW_MEMBER' => 'This user is new' 
    ); 
    return $lang[$phrase]; 
} 
//Then in application where there is text from the site and not from users I would do something like this 
echo lang('NO_PHOTO'); // No photo's available would show here 
?> 

* một số mã được sử dụng từ câu trả lời của brianreavis dưới

+0

Bạn biết rằng bạn không phải sử dụng _ trong một mảng, nhưng có, bạn có lẽ nên sử dụng các phần mở rộng php chứ không phải là cuộn của riêng bạn. – SeanJA

Trả lời

6

Không phát minh lại bánh xe. Sử dụng ví dụ gettext hoặc Zend_Translate.

+8

Nhưng bánh xe là hình vuông! – srcspider

+12

-1. Tại sao? Bởi vì "Đừng sáng tạo lại bánh xe" là quá lạm dụng, với tôi cụm từ có nghĩa là thay vì làm lại một cái gì đó đã được lý tưởng, sử dụng nó! Không, hey, một số anh chàng làm một thư viện mà đá ass, chúng tôi không thực sự quan tâm rằng bạn không thích nó (quá phức tạp) hoặc bất cứ điều gì. – John

+0

Liên kết Zend_Translate là cũ, đối với khung công tác v1 sử dụng [liên kết này] (http://framework.zend.com/manual/1.12/en/zend.translate.html) & cho khung công tác v2 sử dụng [this one] (http://framework.zend.com/manual/current/en/modules/zend.i18n.translating.html). –

5

Đừng viết khuôn khổ ngôn ngữ của riêng bạn. Sử dụng gettext. PHP có tiêu chuẩn bindings mà bạn có thể cài đặt.

+0

Tôi chỉ liếc qua trang chủ gettext ngay hôm nay trước khi đăng bài này, tôi thực sự không thể hiểu được nó hoạt động như thế nào trong một nutshell bạn có thể giải thích một chút về nó? – JasonDavis

+0

jasondavis: nó thực hiện chính xác những gì bạn đang cố gắng làm và nhiều hơn nữa. Khi bạn cài đặt nó, bạn chọn một nơi nào đó để đặt tập tin bản dịch ngôn ngữ của bạn (".po"). Bạn có thể dịch tất cả các chuỗi của mình trong tệp này. Sau đó, trong nguồn của bạn, bạn quấn tất cả các chuỗi đa ngôn ngữ của bạn với gettext() (hoặc thường là một bí danh, '_()') và nó sẽ kéo bản dịch hiện tại của bạn của chuỗi đó cho bạn. Nó cũng cung cấp cho các cụm từ số nhiều và một số tính năng quan trọng khác mà bạn sẽ thấy cần thiết. – Fragsworth

+1

@future reader, tôi sẽ nói, nếu trang web hoặc ứng dụng của bạn không sử dụng hàng trăm đến hàng nghìn từ, thì cách mảng kết hợp tốt hơn gettext. Gettext là cực kỳ lỗi thời trong việc triển khai của nó và có thể là một cơn ác mộng để gỡ lỗi. Tôi chỉ mất ba ngày để làm cho nó hoạt động trên máy chủ của tôi. Nó có nhiều vấn đề và không được duy trì tốt. Tin tôi đi, bạn sẽ gặp phải một số vấn đề của nó. Tốt hơn là sử dụng php-gettext (trình mô phỏng gettext), một số triển khai khác hoặc viết thư viện của riêng bạn. –

-1

lý do tại sao bạn không chỉ cần làm cho nó như mảng đa dimesional ... như thế này

<?php 

$lang = array(
    'EN'=> array(
     'NO_PHOTO'=>'No photo\'s avaiable', 
     'NEW_MEMBER'=>'This user is new', 
    ), 
    'MY'=> array(
     'NO_PHOTO'=>'Tiada gambar', 
     'NEW_MEMBER'=>'Ini adalah pengguna baru', 
    ) 
); 

?> 
+11

Điều này sẽ sử dụng nhiều bộ nhớ hơn mức cần thiết --- vì đây sẽ là tải * mọi ngôn ngữ * cho mọi yêu cầu *. Nó sẽ là tốt hơn để phá vỡ nó thành nhiều tập tin và tải một trong những thích hợp nhất. – brianreavis

18

Nó có lẽ muốn là tốt nhất để xác định một chức năng để xử lý bản đồ ngôn ngữ của bạn. Bằng cách đó, nếu bạn làm muốn thay đổi cách hoạt động sau này, bạn không bị buộc phải quét hàng trăm tập lệnh trong trường hợp bạn đã sử dụng $lang[...] và thay thế bằng thứ khác.

Something như thế này sẽ làm việc và sẽ được tốt đẹp & nhanh:

function lang($phrase){ 
    static $lang = array(
     'NO_PHOTO' => 'No photo\'s available', 
     'NEW_MEMBER' => 'This user is new' 
    ); 
    return $lang[$phrase]; 
} 

Hãy chắc chắn mảng được khai báo bên trong hàm static vì vậy nó không được phân bổ lại mỗi khi hàm được gọi. Điều này đặc biệt quan trọng khi $lang thực sự lớn.

Để sử dụng nó:

echo lang('NO_PHOTO'); 

Đối xử lý nhiều ngôn ngữ, chỉ có chức năng này được định nghĩa trong nhiều file (như en.php, fr.php, vv) và require() một trong những phù hợp cho người dùng.

+2

FYI, giải pháp này thấp hơn đề xuất của Fragsworth: 'gettext'. Gettext chắc chắn là con đường tốt hơn cho loại điều này. Tuy nhiên, đây là cách bạn sẽ làm điều đó nếu bạn đã cuộn hệ thống cơ bản của riêng bạn. – brianreavis

+0

beutifulleeee, ty! – themis

+0

Xin chào, tôi thích giải pháp! Tôi đến từ C# và tôi có một nghi ngờ về cách các biến tĩnh hoạt động trong PHP.Khi bạn khai báo một biến tĩnh trong C#, ví dụ một mảng, nó được giữ trong bộ nhớ và bạn chỉ cần tải nó một lần và giá trị của nó tồn tại giữa các luồng người dùng khác nhau. Nhưng trong PHP nó mất giá trị trong mỗi lần thực hiện theo như tôi biết, và nếu bạn muốn giữ mọi thứ trong bộ nhớ, bạn phải sử dụng các lựa chọn thay thế như APC. Tại sao sau đó @brianreavis bạn khuyên bạn nên làm cho nó tĩnh để không "tái phân bổ" mỗi lần? Cảm ơn bạn! –

10

Điều này có thể làm việc tốt hơn:

function _L($phrase){ 
static $_L = array(
    'NO_PHOTO' => 'No photo\'s available', 
    'NEW_MEMBER' => 'This user is new' 
); 

    return (!array_key_exists($phrase,$_L)) ? $phrase : $_L[$phrase]; 
} 

Thats những gì tôi sử dụng cho bây giờ. Nếu ngôn ngữ không được tìm thấy, nó sẽ trả về cụm từ, thay vì một lỗi.

Bạn nên lưu ý rằng một mảng có thể chứa không quá ~ 65500 mục. Nên là đủ nhưng tốt, chỉ cần nói.

Dưới đây là một số mã mà tôi sử dụng để kiểm tra ngôn ngữ của người dùng:

<?php 
function setSessionLanguageToDefault() { 
    $ip=$_SERVER['REMOTE_ADDR']; 
    $url='http://api.hostip.info/get_html.php?ip='.$ip; 
    $data=file_get_contents($url); 
    $s=explode (':',$data); 
    $s2=explode('(',$s[1]); 

    $country=str_replace(')','',substr($s2[1], 0, 3)); 

    if ($country=='us') { 
     $country='en'; 
    } 

    $country=strtolower(ereg_replace("[^A-Za-z0-9]", "", $country)); 
    $_SESSION["_LANGUAGE"]=$country; 
} 

if (!isset($_SESSION["_LANGUAGE"])) { 
    setSessionLanguageToDefault(); 
} 

if (file_exists(APP_DIR.'/language/'.$_SESSION["_LANGUAGE"].'.php')) { 
    include(APP_DIR.'/language/'.$_SESSION["_LANGUAGE"].'.php'); 
} else { 
    include(APP_DIR.'/language/'.DEFAULT_LANG.'.php'); 
} 

?> 

của nó vẫn chưa xong, nhưng tôi cũng nghĩ rằng đây có thể giúp đỡ rất nhiều.

1

Vì các câu trả lời khác không thực sự trả lời tất cả các câu hỏi, tôi sẽ tìm câu trả lời đó trong câu trả lời của tôi cộng với việc đưa ra một giải pháp thay thế hợp lý.

1) I18n viết tắt của Internationalization và có một số điểm tương đồng với I-mười tám-n.

2) Theo ý kiến ​​trung thực, gettext là một sự lãng phí thời gian.

3) Cách tiếp cận của bạn có vẻ tốt. Những gì bạn nên tìm là các biến ngôn ngữ. WoltLab Community Framework 2.0 triển khai hệ thống ngôn ngữ hai chiều. Đối với một lần có các biến ngôn ngữ được lưu trong cơ sở dữ liệu và bên trong một mẫu chỉ sử dụng tên của biến mà sau đó sẽ được thay thế bằng nội dung của biến trong ngôn ngữ hiện tại (nếu có). Phần thứ hai của hệ thống cung cấp một cách để lưu nội dung do người dùng tạo bằng nhiều ngôn ngữ (yêu cầu nhập bằng nhiều ngôn ngữ).

Về cơ bản, bạn có văn bản giao diện được xác định bởi nhà phát triển và nội dung do người dùng xác định. Văn bản đa ngôn ngữ của nội dung được lưu trong các biến ngôn ngữ và tên của biến ngôn ngữ sau đó được sử dụng làm giá trị cho trường văn bản trong bảng nội dung cụ thể (cũng như nội dung ngôn ngữ đơn).

Cấu trúc của WCF thật đáng buồn theo cách tái sử dụng mã bên ngoài khung công tác rất khó nhưng bạn có thể sử dụng nó làm nguồn cảm hứng. Phạm vi của hệ thống chỉ phụ thuộc vào những gì bạn muốn đạt được với trang web của bạn. Nếu nó sẽ lớn hơn bạn chắc chắn nên xem xét hệ thống WCF. Nếu nó nhỏ một vài tập tin ngôn ngữ chuyên dụng (de.php, en.php, vv), từ đó chính xác cho ngôn ngữ hiện tại được bao gồm, sẽ làm.

+0

* 2) Theo ý kiến ​​trung thực của tôi, gettext là một sự lãng phí thời gian. * - Thật vậy! – almosnow

1

Thật không may gettext không hoạt động tốt và có vấn đề trong các tình huống khác nhau như trên hệ điều hành khác nhau (Windows hoặc Linux) và làm cho nó hoạt động là rất khó khăn.

Ngoài ra, yêu cầu bạn đặt nhiều biến môi trường và tên miền và điều này không có ý nghĩa gì.

Nếu nhà phát triển chỉ muốn nhận bản dịch của văn bản, anh ấy chỉ nên đặt đường dẫn tệp .mo và nhận bản dịch có một hàm như dịch ("hello", "en_EN"); Với gettext, điều này là không thể.

0

Bạn có thể làm điều này:

class T { 
const language = "English"; 
const home = "Home"; 
const blog = "Blog"; 
const forum = "Forum"; 
const contact = "Support"; 
} 

Bạn sẽ có một tập tin như thế này cho mỗi ngôn ngữ. Để sử dụng văn bản:

There is no place like <?=T::home?>. 

Nhược điểm là nếu bạn thêm một hằng số mới, bạn phải làm điều đó cho mỗi langauge tập tin. Nếu bạn quên một trang, trang của bạn sẽ bị ngắt cho ngôn ngữ đó. Đó là một chút khó chịu, nhưng nó là hiệu quả vì nó không cần phải tạo ra một mảng kết hợp lớn và có thể các giá trị thậm chí có được inlined.

lẽ truy cập có thể được cải thiện, ví dụ:

class T { 
    const home = "home"; 

    public static function _ ($name) { 
     $value = @constant("self::$name"); 
     return $value ? $value : $name; 
    } 

    // Or maybe through an instance: 
    public function __get ($name) { 
     $value = @constant("self::$name"); 
     return $value ? $value : $name; 
    } 
} 
echo "There is no " . T::_("place") . " like " . T::_("home"); 
$T = new T(); 
echo "There is no " . $T->place . " like " . $T->home; 

Chúng tôi vẫn tránh mảng và dựa vào constant để làm tra cứu, mà tôi giả định là đắt hơn so với sử dụng các hằng số trực tiếp. Phía lên là tra cứu có thể sử dụng một dự phòng khi không tìm thấy khóa.

Các vấn đề liên quan