创建多语言站点(通过复制页面树的方式)

此教程将给出一种Wagtail中通过复制页面树的方式,创建多语言站点的方法。

比如:

  1. /
  2. en/
  3. about/
  4. contact/
  5. fr/
  6. about/
  7. contact/

根页面

根页面(/)需要去侦测浏览器语言并将不同语言的浏览器请求,转发到正确语言的主页(/en//fr/)。根页面应位处站点根部(那里也是主页通常的所在)。

这里就必须设置 Django 的LANGUAGES 设置项,从而不会将那些非英语或法语的用户,重定向到不存在的页面。

  1. # settings.py
  2. LANGUAGES = (
  3. ('en', _("English")),
  4. ('fr', _("French")),
  5. )
  1. # models.py
  2. from django.utils import translation
  3. from django.http import HttpResponseRedirect
  4. from wagtail.core.models import Page
  5. class LanguageRedirectionPage(Page):
  6. def serve(self, request):
  7. # 此方法仅会返回一个在 Django 的 LANGUAGE 设置项中的某个语言
  8. language = translation.get_language_from_request(request)
  9. return HttpResponseRedirect(self.url + language + '/')

将全部页面链接起来

将同一页面的不同语言版本链接在一起,从而允许访问者可以轻松地在语言之间进行切换,将是有用的。但又不打算过多地增加站点编辑的负担,理想情况下,站点编辑只需将这些相同页面的一个版本,与其他版本链接起来,那么其他版本之间的链接将隐式地创建出来。

因为此做法需要添加到所有翻译的页面类型,所以最好将此做法放到混入中(a mixin)。

下面是一个如何实现此做法的示例(英语作为主语言,法语/西班牙语作为替代语言):

  1. from wagtail.core.models import Page
  2. from wagtail.admin.edit_handlers import MultiFieldPanel, PageChooserPanel
  3. class TranslatablePageMixin(models.Model):
  4. # 每种替代语言对应一个链接
  5. # 这些属性与方法,应只应用在主语言的页面上(也就是英语)
  6. french_link = models.ForeignKey(Page, null=True, on_delete=models.SET_NULL, blank=True, related_name='+')
  7. spanish_link = models.ForeignKey(Page, null=True, on_delete=models.SET_NULL, blank=True, related_name='+')
  8. panels = [
  9. PageChooserPanel('french_link'),
  10. PageChooserPanel('spanish_link'),
  11. ]
  12. def get_language(self):
  13. """
  14. 此方法返回的时该页面的语言代码。
  15. """
  16. # 通过对本页面的祖先进行查找,以找到他的语言代码
  17. # 语言主页位于深度 3 处(The language homepage is located at depth 3)
  18. language_homepage = self.get_ancestors(inclusive=True).get(depth=3)
  19. # 语言主页的别名,应总是被设置为语言代码
  20. return language_homepage.slug
  21. # 用于找出本页面主语言的方法
  22. # 这是通过对上面的链接进行反向追溯完成的(this works by reversing the above links)
  23. def english_page(self):
  24. """
  25. 该方法找出本页面的英语版本
  26. """
  27. language = self.get_language()
  28. if language == 'en':
  29. return self
  30. elif language == 'fr':
  31. return type(self).objects.filter(french_link=self).first().specific
  32. elif language == 'es':
  33. return type(self).objects.filter(spanish_link=self).first().specific
  34. # 这里需要某种找出本页面的每种替代语言的一个版本的方法。
  35. # 这些方法工作原理一样。他们首先找出页面的主要语言版本(也就是英语)。
  36. # 然后从主要语言版本开始,就只需跟随链接,就能获得相应语言的正确版本了。
  37. def french_page(self):
  38. """
  39. 此方法找出该页面的法语版本
  40. """
  41. english_page = self.english_page()
  42. if english_page and english_page.french_link:
  43. return english_page.french_link.specific
  44. def spanish_page(self):
  45. """
  46. 此方法找出该页面的西班牙版本
  47. """
  48. english_page = self.english_page()
  49. if english_page and english_page.spanish_link:
  50. return english_page.spanish_link.specific
  51. class Meta:
  52. abstract = True
  53. class AboutPage(Page, TranlatablePageMixin):
  54. ...
  55. content_panels = [
  56. ...
  57. MutliFieldPanel(TranslatablePageMixin.panels, '语言链接')
  58. ]
  59. class ContactPage(Page, TranslatablePageMixin):
  60. ...
  61. content_panels = [
  62. ...
  63. MultiFieldPanel(TranslatablePageMixin.panels, '语言链接')
  64. ]

随后在模板中就可以向下面这样,利用上这些方法了:

{% raw %}

  1. {% if page.english_page and page.get_language != 'en' %}
  2. <a href="{{ page.english_page.url }}">{% trans "View in English" %}</a>
  3. {% endif %}
  4. {% if page.french_page and page.get_language != 'fr' %}
  5. <a href="{{ page.english_page.url }}">{% trans "View in English" %}</a>
  6. {% endif %}
  7. {% if page.spanish_page and page.get_language != 'es' %}
  8. <a href="{{ page.english_page.url }}">{% trans "View in English" %}</a>
  9. {% endif %}

{% endraw %}