2011-10-31 10 views
11

Tôi đang gặp sự cố khi nhận dữ liệu từ cơ sở dữ liệu của mình mà tôi đã tạo ra là đa ngôn ngữ và tôi hy vọng ai đó ở đây có thể giúp tôi.Làm thế nào để sử dụng Yii với mô hình cơ sở dữ liệu đa ngôn ngữ?

Tôi đã chia tất cả các bảng của mình thành 2 phần; bảng “phổ quát” (không chứa bất kỳ văn bản nào cần được dịch) và bảng chứa tất cả các trường cần được dịch cùng với bản dịch của chúng.

bảng Ví dụ:

base_material 
    id 
    picture 
base_material_i18n 
    base_material_id 
    localization_id 
    name 
    description 
    review_status 
    review_notes 
localization 
    id 
    language_name 

Query để có được những bản dịch (sử dụng tiếng Anh (en) như một ngôn ngữ giảm trở lại nếu không có bản dịch có sẵn):

SELECT o.id 
    , o.type 
    , o.code 
    , o.position 
    , ifnull(t.name,d.name) name 
    , ifnull(t.description,d.description) description 
    FROM base_material o 
     INNER JOIN base_material_i18n d 
       ON (o.id=d.base_material_id) 
     LEFT OUTER JOIN base_material_i18n t 
        ON (d.base_material_id=t.base_material_id AND t.localization_id='nl') 
WHERE d.localization_id='en' 

Câu hỏi của tôi là như thế nào Tôi có thể tự động nhận được những bản dịch đó (với ngôn ngữ rơi ngược như trong truy vấn này) gắn liền với mô hình của tôi trong Yii khi tôi đang tìm kiếm các đối tượng base_material? (Đây chỉ là 1 bảng ví dụ, nhưng hầu như tất cả các bảng của tôi (20+) được xây dựng theo cách này, vì vậy nếu có thể tôi sẽ cần một cái gì đó linh hoạt)

Ví dụ về hệ thống hiện tại sử dụng những gì tôi cần là Propel : http://propel.posterous.com/propel-gets-i18n-behavior-and-why-it-matters

Bất kỳ ý tưởng nào về cách thực hiện điều đó? Tôi đã kiểm tra các phần mở rộng Yii hiện có liên quan đến các trang đa ngôn ngữ (như Multilingual Active Record), nhưng tất cả đều sử dụng một thiết kế cơ sở dữ liệu khác (thông tin chung + ngôn ngữ thu gọn trong bảng chính, bản dịch trong bảng i18n), và tôi không chắc chắn cách thay đổi các tiện ích mở rộng đó để sử dụng loại mô hình DB của tôi.

Nếu ai đó biết cách thay đổi tiện ích mở rộng hiện tại để có thể sử dụng loại chương trình DB của tôi, thì điều đó hoàn toàn tuyệt vời và có lẽ là cách tốt nhất để thực hiện việc này.

Chỉnh sửa: Tôi đã thêm tiền thưởng vì tôi vẫn không thể tìm thấy bất kỳ điều gì về cách cho phép Propel làm việc với Yii (có tồn tại phần mở rộng cho Doctrine, nhưng Doctrine không hỗ trợ kiểu DB này với bản dịch hoặc), cũng không phải bất kỳ thông tin nào khác về cách xử lý việc này bằng cách sử dụng phần mở rộng Yii hiện có hoặc với phạm vi.

Chỉnh sửa: 98 lần xem nhưng chỉ 3 phiếu bầu và 1 nhận xét. Tôi không thể không cảm thấy như tôi đang làm điều gì đó sai ở đây, có thể là trong câu hỏi của tôi hoặc thiết kế ứng dụng/cơ sở dữ liệu; hoặc đó là vấn đề của tôi chỉ là rất độc đáo (điều đó sẽ làm tôi ngạc nhiên, vì tôi không nghĩ rằng thiết kế cơ sở dữ liệu đa ngôn ngữ của tôi là vô lý ;-). Vì vậy, nếu có ai biết giải pháp toàn diện tốt hơn cho các trang đa ngôn ngữ với Yii và/hoặc Propel (ngoài các tiện ích mở rộng hiện tại mà tôi thực sự không thích do trùng lặp các trường văn bản) hoặc điều gì đó tương tự, vui lòng cho tôi biết cũng.

Cảm ơn trước!

+0

Nếu có thêm câu hỏi nào về lý do hoặc điều gì, hoặc nếu một điều gì đó không hoàn toàn rõ ràng, chỉ cần hỏi :-) – Xuntar

+1

Xin lỗi bạn đang có một khó tìm ra câu trả lời. Tôi sẽ cố gắng giúp đỡ nếu tôi có thể. Vì vậy, về cơ bản bạn chỉ muốn một truy vấn chọn bản dịch được chọn và tiếng Anh cho bất kỳ giá trị nào mà ngôn ngữ được dịch cho mục đó không tồn tại đúng? Tôi muốn chắc chắn rằng tôi hiểu câu hỏi của bạn trước;) – Chiramisu

+0

Xin chào Chiramusi và cảm ơn sự giúp đỡ của bạn. Các truy vấn tôi đã đăng trong câu hỏi của tôi hoạt động khi tôi chạy nó trong cơ sở dữ liệu của tôi, nhưng tôi tự hỏi làm thế nào tôi có thể làm điều này nhiều hơn "automagically". Phần mở rộng mà tôi đã liên kết để thêm bản dịch vào mô hình theo cách tự động và tôi muốn một cái gì đó tương tự cho cơ sở dữ liệu của tôi (phần mở rộng sử dụng lược đồ db khác) hoặc ý tưởng về cách thay đổi phần mở rộng đó để sử dụng bảng và thiết kế của tôi. Nếu không, nếu bạn biết cách sử dụng Propel với Yii, điều đó cũng sẽ rất tuyệt vời (vì Propel có kiểu bản dịch cơ sở dữ liệu này được tích hợp sẵn). – Xuntar

Trả lời

2

Tôi cũng đang tìm giải pháp chung để triển khai mô hình i18n thành Yii. Gần đây tôi đã chọn một lược đồ cơ sở dữ liệu rất giống với một dự án như bạn. Sự khác biệt duy nhất là, tôi không sử dụng một bảng ngôn ngữ riêng biệt, tôi lưu trữ thông tin ngôn ngữ trong bảng i18n.

Giải pháp sau đây không có câu lệnh SQL tùy chỉnh, nhưng tôi nghĩ điều này có thể được thực hiện với các tham số quan hệ, nếu bạn đang làm việc với khóa ngoài trong cơ sở dữ liệu của mình (ví dụ:MySQL InnoDB) GII sẽ tạo ra mối quan hệ giữa bạn và base_material bảng base_material_i18n, như

class BaseMaterial extends CActiveRecord 

public function relations() 
{ 
    return array(
     'baseMaterialI18ns' => array(self::HAS_MANY, 'base_material_i18n', 'id'), 
    ); 
} 



class BaseMaterialI18n extends CActiveRecord 

public function relations() 
{ 
    return array(
     'baseMaterial' => array(self::BELONGS_TO, 'base_material', 'id'), 
    ); 
} 

Bây giờ bạn muốn có thể truy cập dịch của bạn bằng cách sử dụng các ký hiệu đối tượng cho mối quan hệ.

$model = BaseMaterial::model()->with('baseMaterialI18ns')->findByPk(1); 
foreach($model->baseMaterialI18ns AS $translation) { 
    if ($translation->language != "the language I need") continue: 
    // do something with translation data ... 
} 

Tôi nghĩ về việc tạo ra một hành vi hoặc lớp cơ sở cho những mô hình mà sẽ đóng vai trò một như helper để quản lý các bản dịch - mã giả:

I18nActiveRecord extends CActiveRecord 

protected $_attributesI18n; 

// populate _attributesI18n on query ... 

public function __get($name) { 
    if(isset($this->_attributesI18n['language_I_need'][$name])) 
    return $this->_attributesI18n[$name]; 
    else if(isset($this->_attributesI18n['fallback_language'][$name])) 
    return $this->_attributesI18n[$name]; 
    else 
    parent::__get(); 
} 

CActiveRecord __get() source

Có nhiều việc phải được thực hiện để tìm bản ghi i18n cần thiết, bạn cũng có thể giới hạn thêm tùy chọn with() để cải thiện hiệu suất và giảm phân tích cú pháp ở phía PHP.

Nhưng có thể có các trường hợp sử dụng khác nhau cách xác định giá trị, ví dụ: tất cả các bản dịch, bản dịch hoặc dự phòng, không có dự phòng (giá trị trống). Kịch bản có thể hữu ích ở đây.

PS: Tôi sẽ tham gia github project!

+0

Cảm ơn câu trả lời của bạn! Thực tế phần thứ hai của câu trả lời của bạn là nhiều hơn hoặc ít hơn những gì tôi muốn tìm kiếm. Phần đầu tiên tôi hoàn toàn hiểu và sẽ làm việc, nhưng là quá phiền hà với tất cả các bảng và tất cả các lĩnh vực. Rõ ràng bạn có nhiều kinh nghiệm với Yii hơn tôi; nó sẽ có thể xây dựng một chút về lớp cơ sở đó? Tôi có ý tưởng về những gì bạn cố gắng làm, nhưng không có một đầu mối về cách thực sự làm điều đó. – Xuntar

+2

Chỉ cần tạo một hành vi cho điều đó.Tôi thấy rằng nó sạch hơn nếu bạn truy cập các bản dịch bằng một phương thức t(). Chúng ta hãy xem https://github.com/schmunk42/p3extensions/blob/master/behaviors/P3TranslationBehavior.php – schmunk

+0

Điều này có vẻ rực rỡ, cảm ơn vì đã giữ cho tôi (và câu hỏi này) được cập nhật! Tôi nghĩ rằng tôi có được ý chính về cách nó hoạt động và cách sử dụng nó và tôi sẽ có thể thử nó vào tối mai. Tôi giả sử 'mối quan hệ' => 'daContentTranslations' sẽ trở thành 'quan hệ' => 'baseMaterialI18ns' bằng cách sử dụng phần đầu tiên của mã ví dụ trong câu trả lời của bạn? Và nếu tôi sử dụng cùng một tên quan hệ trên tất cả các bảng của tôi, điều này sẽ làm việc trên tất cả chúng? Lần nữa; cảm ơn bạn rất nhiều! – Xuntar

4

Bạn đã thử http://www.yiiframework.com/extension/i18n-columns/ (dựa trên http://www.yiiframework.com/extension/stranslateablebehavior/)?

Cách tiếp cận thay thế, đơn giản hơn bằng cách thêm các trường bảng mới theo kiểu {field} _ {language code} và sau đó đặt trường đã dịch trong mô hình gốc thành bản dịch của ngôn ngữ hiện tại trên afterFind.

Về bản chất, nó sẽ giúp bạn bắt đầu và chạy với các trường có thể dịch được với nội dung đã dịch được tìm nạp "tự động", cho tốt và xấu :). Thêm và xóa ngôn ngữ (= cột) được thực hiện bằng cách sử dụng di chuyển.

+0

tại sao không có cơ thể nào nói lời chào này? –

0

Bạn có thể thử sử dụng phần mở rộng CRUD đa ngôn ngữ đơn giản. nó rất đơn giản để sử dụng và modificate. bạn chỉ cần thêm trường ngôn ngữ vào bảng của mình. chỉ xem mô tả tại đây: http://all-of.me/yii-multilingual-crud/ nó ở trạng thái alpha, nhưng đã thử trên một vài dự án. bạn có thể dễ dàng sửa đổi nó hoặc liên hệ với tác giả để sửa hoặc thêm các tính năng