3

フラスコアプリケーションインスタンスを備えたサーバーが1つあり、DNSによってこのサーバーにマップされたドメインがいくつかあります。

私のサイトは、ホストとプレフィックスによっていくつかの言語をサポートする必要があります。

mysite.com - english
mysite.com/fr - franch
mysite.ru - russian
mysite.ru/by - belarusian
localhost or other unknown host without language prefix - default language (english)

ダブルルート登録/endpoint/<lang>/endpointリロードされた関数を使用して実装しましたが、機能しますが、関数url_forのカスタムエラーページを実装する必要があります。abort

mysite.com/wrong-url-there - mysite.com/404.html (english)
mysite.com/fr/wrong-url-there - mysite.com/fr/404.html (franch)
mysite.ru/wrong-url-there - mysite.ru/404.html (russian)
mysite.ru/by/wrong-url-there - mysite.ru/by/404.html (belorusian)

そして、私はこれに対する解決策を見ていません。私の実装は悪いと思います、そして私はそれを改善しなければなりません。サイトの言語ルートごとに、事前定義された言語を使用してアプリケーションのインスタンスを1つ作成するか、ブループリントを使用する必要があると思いますが、まだ解決策が見つかりません。

誰かが私にこのurl多言語サポートをflaskまたはwsgiまたはnginxでどのように解決するかアドバイスを与えることができますか?

4

4 に答える 4

4

これは公式ドキュメントにあります:http://flask.pocoo.org/docs/patterns/urlprocessors/(これは基本的にMatthew Scraggのものと同じ答えです)。

于 2013-04-12T10:27:12.430 に答える
3

私は数ヶ月前に似たようなことに取り組みました。少し変更してgithubにプッシュしました。テンプレートを言語ニュートラルにすることができない場合は、codegeekが提案したことを実行できます。この方法を使用すると、必要なテンプレートファイルを削減できます。

https://github.com/scragg0x/Flask-Localisation-例

mysite.py

from flask import Flask, Blueprint, g, redirect, request

app = Flask(__name__)

mod = Blueprint('mysite', __name__, url_prefix='/<lang_code>')

sites = {
    'mysite.com': 'en',
    'myothersite.com': 'fr'
}

@app.url_defaults
def add_language_code(endpoint, values):
    values.setdefault('lang_code', g.lang_code)

@app.url_value_preprocessor
def pull_lang_code(endpoint, values):
    url = request.url.split('/', 3)
    g.lang_code = sites[url[2]]

@mod.url_defaults
def add_language_code(endpoint, values):
    values.setdefault('lang_code', g.lang_code)

@mod.url_value_preprocessor
def pull_lang_code(endpoint, values):
    g.lang_code = values.pop('lang_code')

@app.route('/')
@mod.route('/')
def index():
    # Use g.lang_code to pull localized data for template
    return 'lang = %s' % g.lang_code

app.register_blueprint(mod)

tests.py

import os
import unittest
import re
import requests
import urllib2
import json
from mysite import app

class MySiteTestCase(unittest.TestCase):

    def setUp(self):
        app.config['TESTING'] = True
        app.config['SERVER_NAME'] = 'mysite.com'
        self.domain = 'http://mysite.com/'
        self.app = app.test_client()

    def tearDown(self):
        pass

    def test_en_index(self):
        rv = self.app.get('/en/', self.domain)
        self.assertEqual(rv.data, 'lang = en')
        print self.domain, rv.data

    def test_fr_index(self):
        rv = self.app.get('/fr/', self.domain)
        self.assertEqual(rv.data, 'lang = fr')
        print self.domain, rv.data

    def test_default(self):
        rv = self.app.get('/', self.domain)
        self.assertEqual(rv.data, 'lang = en')
        print self.domain, rv.data

class MyOtherSiteTestCase(unittest.TestCase):

    def setUp(self):
        app.config['TESTING'] = True
        app.config['SERVER_NAME'] = 'myothersite.com'
        self.domain = 'http://myothersite.com/'
        self.app = app.test_client()

    def tearDown(self):
        pass

    def test_en_index(self):
        rv = self.app.get('/en/', self.domain)
        self.assertEqual(rv.data, 'lang = en')
        print self.domain, rv.data

    def test_fr_index(self):
        rv = self.app.get('/fr/', self.domain)
        self.assertEqual(rv.data, 'lang = fr')
        print self.domain, rv.data

    def test_default(self):
        rv = self.app.get('/', self.domain)
        self.assertEqual(rv.data, 'lang = fr')
        print self.domain, rv.data

if __name__ == '__main__':
    unittest.main()
于 2013-02-07T04:57:43.387 に答える
2

免責事項:このコードはテストされていません。私はあなたにこれにアプローチする方法の球場のアイデアを与えているだけです。

ブループリントをFlask-Babelのような拡張機能と組み合わせて使用​​することをお勧めします。たとえば、次のようなことができます。

views.py

mysitebp = Blueprint('mysitebp',__name__)

次に、アプリケーションパッケージ(通常__init__.py)で、次のことを実行できます。

__init__.py

from mysite.views import mysitebp
app = Flask(__name__)
app.register_blueprint(mysitebp,url_prefix='/en/',template_folder='en')
app.register_blueprint(mysitebp,url_prefix='/fr',template_folder='fr')

..等々

ディレクトリ構造は次のようになります。

mysite/
__init__.py
views.py
templates/
    base.html
    404.html
    en/
        en.html
    fr/
        french.html

Flask-Babelは、404.htmlなどの翻訳に役立ちます。

于 2013-02-04T14:49:52.193 に答える
0

私自身の解決策:

from flask import Flask, g, render_template, redirect, request


app = Flask(__name__)

default_language = 'en'
language_urls = {
    'en': 'mysite.com',
    'fr': 'mysite.com/fr',
    'ru': 'mysite.ru',
    'by': 'mysite.ru/by',
}
languages = ','.join(language_urls.keys())


def get_language_by_request(request_host, request_path):
    '''
    Looking bad, but work.
    I cab't use request.view_args there,
    because this can't detect language for 404 pages
    like mysite.com/fr/unknown-page
    '''
    request_host_path = request_host + request_path
    request_paths = request_host_path.split('/', 2)
    if (len(request_paths) > 1 and request_paths[1] in language_urls.keys()):
        request_language_prefix = request_paths[1]
        return request_language_prefix
    for language, url in language_urls.items():
        host_prefix = url.split('/')
        if len(host_prefix) == 1:
            host, = host_prefix
            if request_host == host:
                return language
    return default_language


def get_language_url_parameter_value(language, request_host):
    host_prefix = language_urls[language]
    if host_prefix == request_host:
        return None
    return language


def get_redirection_url_by_request(request_host, request_path, request_url):
    '''
    Looking bad, but work.
    I cab't use request.view_args there,
    because this can't detect language for 404 pages
    like mysite.com/fr/unknown-page
    '''
    request_host_path = request_host + request_path
    request_paths = request_host_path.split('/', 2)
    request_language_prefix = None
    if (len(request_paths) > 1 and request_paths[1] in language_urls.keys()):
        request_language_prefix = request_paths[1]
    hosts = []
    for language, url in language_urls.items():
        host_prefix = url.split('/')
        if len(host_prefix) == 1:
            host, = host_prefix
            language_prefix = None
        else:
            host, language_prefix = host_prefix
        if request_host == host and request_language_prefix == language_prefix:
            return None
        hosts.append(host)
    if request_host not in hosts:
        return None
    if request_language_prefix:
        request_host_prefix = request_host + '/' + request_language_prefix
        host_prefix = language_urls[request_language_prefix]
        return request_url.replace(request_host_prefix, host_prefix)
    return None


@app.url_defaults
def set_language_in_url(endpoint, values):
    if '_lang' not in values and hasattr(g, 'language_url_value'):
        values['_lang'] = g.language_url_value


@app.url_value_preprocessor
def get_language_from_url(endpoint, values):
    g.language = get_language_by_request(request.host, request.path)
    g.language_url_value = get_language_url_parameter_value(g.language, request.host)
    if values and '_lang' in values:
        del values['_lang']


@app.before_request
def check_language_redirection():
    redirection_url = get_redirection_url_by_request(request.host, request.path, request.url)
    return redirect(redirection_url) if redirection_url else None


@app.route('/')
@app.route('/<any(%s):_lang>/' % languages)
def home():
    return render_template('home.html')


@app.route('/other/')
@app.route('/<any(%s):_lang>/other/' % languages)
def other():
    return render_template('other.html')

flask-loginブループリントも使用しており、ブループリントごとに異なる言語で複数のログインページを設定できないため、ブループリントは使用していません。たとえば、ページにログインが必要な場合、flaskはログインページにリダイレクトし、このページの言語を更新する必要があります。mysite.com/loginまた、ログインページは、いくつかのリダイレクトなしでは、mysite.com/fr/loginなどにすることはできません。

UPD:request.view_args言語の検出やリダイレクトには使用できません。この場合、エラーページの言語をmysite.com/fr/wrong-page-thereendpointおよびを検出できませんview_args)として検出できないためです。この問題を回避するために、haskを使用できます。URLルールをとして追加し/<lang_code>/<path:path>、そこで404エラーを発生させます。

于 2013-02-19T13:36:44.107 に答える