سؤال

ما هي أنظف طريقة لإضافة بادئة إلى كل عنوان URL في CakePhP ، مثل معلمة اللغة؟

http://example.com/en/controller/action
http://example.com/ru/admin/controller/action

يحتاج إلى العمل مع البادئات "الحقيقية" مثل admin, ، ومن الناحية المثالية عنوان URL العاري /controller/action يمكن إعادة توجيهها إلى /DEFAULT-LANGUAGE/controller/action.

إنه يعمل في تطبيق مجهز رجوعًا بالنسبة لي الآن ، لكنه كان نوعًا من الاختراق ، وأحتاج إلى تضمين معلمة اللغة باليد في معظم الروابط ، وهذا ليس جيدًا.

لذا فإن السؤال ذو شقين:

  • ما هي أفضل طريقة لهيكلة المسارات ، وبالتالي يتم تضمين معلمة اللغة ضمنيًا بشكل افتراضي دون الحاجة إلى تحديد كل مسار محدد حديثًا؟
    • Router::connect('/:controller/:action/*', ...) يجب أن تشمل ضمنيا البادئة.
    • يجب أن تكون المعلمة متاحة في $this->params['lang'] أو في مكان مشابه لتقييمه في AppController::beforeFilter().
  • كيف تحصل على Router::url() لتضمين البادئة تلقائيًا في عنوان URL ، إن لم يكن محددًا بشكل صريح؟
    • Router::url(array('controller' => 'foo', 'action' => 'bar')) يجب أن تعود /en/foo/bar
    • حيث Controller::redirect(), Form::create() او حتى Router::url() تحتاج مباشرة إلى الحصول على نفس السلوك ، والتجاوز كل وظيفة واحدة ليس خيارًا حقًا. Html::image() على سبيل المثال ، يجب أن تنتج عنوان URL بدون بادئة.

يبدو أن الأساليب التالية تتصل بها Router::url.

  • Controller::redirect
  • Controller::flash
  • Dispatcher::__extractParams عبر Object::requestAction
  • Helper::url
  • JsHelper::load_
  • JsHelper::redirect_
  • View::uuid, ، ولكن فقط لجيل التجزئة

من بين هؤلاء يبدو أن طرق وحدة التحكم والمساعد تحتاج إلى تجاوزها ، يمكنني العيش بدون JsHelper. ستكون فكرتي هي كتابة وظيفة عامة في AppController أو ربما فقط في bootstrap.php للتعامل مع المعلمة إدراج. ستستخدم وحدة التحكم والمساعد المتطابق هذه الوظيفة ، كما أود أن أرغب في الاتصال يدويًا Router::url. هل سيكون هذا كافيًا؟

هل كانت مفيدة؟

المحلول

اقترح Rchavik من IRC هذا الرابط: تبديل اللغة القائمة على عنوان URL CakePhP للتدويل وتوطين I18N و L10N

بشكل عام ، يبدو أن التجاوز Helper::url قد يكون الحل.

نصائح أخرى

هذا هو في الأساس كل الشفرة التي قمت بتطبيقها لحل هذه المشكلة في النهاية (على الأقل أعتقد أن هذا كل شيء ؛-)):

/config/bootstrap.php

define('DEFAULT_LANGUAGE', 'jpn');

if (!function_exists('router_url_language')) {
    function router_url_language($url) {
        if ($lang = Configure::read('Config.language')) {
            if (is_array($url)) {
                if (!isset($url['language'])) {
                    $url['language'] = $lang;
                }
                if ($url['language'] == DEFAULT_LANGUAGE) {
                    unset($url['language']);
                }
            } else if ($url == '/' && $lang !== DEFAULT_LANGUAGE) {
                $url.= $lang;
            }
        }

        return $url;
    }
}

/config/core.php

Configure::write('Config.language', 'jpn');

/app_helper.php

class AppHelper extends Helper {

    public function url($url = null, $full = false) {
        return parent::url(router_url_language($url), $full);
    }

}

/app_controller.php

class AppController extends Controller {

    public function beforeFilter() {
        if (isset($this->params['language'])) {
            Configure::write('Config.language', $this->params['language']);
        }
    }

    public function redirect($url, $status = null, $exit = true) {
        parent::redirect(router_url_language($url), $status, $exit);
    }

    public function flash($message, $url, $pause = 1) {
        parent::flash($message, router_url_language($url), $pause);
    }

}

/config/routes.php

Router::connect('/', array('controller' => 'pages', 'action' => 'display', 'home'));
Router::connect('/pages/*', array('controller' => 'pages', 'action' => 'display'));
Router::connect('/:language/', array('controller' => 'pages', 'action' => 'display', 'home'), array('language' => '[a-z]{3}'));
Router::connect('/:language/pages/*', array('controller' => 'pages', 'action' => 'display'), array('language' => '[a-z]{3}'));
Router::connect('/:language/:controller/:action/*', array(), array('language' => '[a-z]{3}'));

هذا يسمح عناوين URL الافتراضية مثل /controller/action لاستخدام اللغة الافتراضية (JPN في حالتي) ، وعنوان URL مثل /eng/controller/action لاستخدام لغة بديلة. يمكن تغيير هذا المنطق بسهولة في router_url_language() وظيفة.

لكي يعمل هذا ، أحتاج أيضًا إلى تحديد طريقين لكل مسار ، واحد يحتوي على /:language/ المعلمة وواحد بدون. على الأقل لم أستطع معرفة كيفية القيام بذلك بطريقة أخرى.

قد تكون هناك طريقة أسهل لتخزين اللغة المختارة في ملف تعريف الارتباط ومن ثم لا تضطر إلى إعادة كتابة جميع عناوين URL. يمكنك أيضًا اكتشاف لغة متصفح المستخدم تلقائيًا.

لكن, ، من غير المرجح أن تستلم محركات البحث اللغات المختلفة وستفقد اللغة أيضًا إذا حاول شخص ما مشاركة الرابط.

لكن أحب الحل الكامل الذي نشرته ، شاملًا جدًا ، شكرًا. :-)

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top