开发者

Django: Slug in Vietnamese

A site in Vietnamese, it is virtually no different to English. However, there is a problem that is slug. When I type characters such as "ư", "ơ", "á",... Django is not identified. Solution here is to replace characters开发者_C百科 that do not sign into. Eg:

ư -> u 
ơ -> o 
á -> a 

One from "những-viên-kẹo" will become "nhung-vien-keo". However, I do not know how to do this. Someone help me. Thank you very much!


[edit]

I take it back, django's django.template.defaultfilters.slugify() does what you want, using unicodedata.normalize and .encode('ascii', 'ignore'). Just feeding your string into slugify will work:

from django.template.defaultfilters import slugify
print slugify(u"những-viên-kẹo")

To do this automatically, add this to the .save() method in your models:

from django.template.defaultfilters import slugify
MyModel(models.Model):
    title = models.CharField(max_length=255)
    slug  = models.SlugField(blank=True)

    def save(self, *args, **kwargs):
        if not self.slug:
            self.slug = slugify(self.title)
        super(MyModel, self).save(*args, **kwargs)

The slolution I wrote ealier (below) would still be useful for languages that require additional characters in their translation, eg German's ü->ue, ß->ss etc.

[original post]

Python allows you to use a translation dict to map characters to a replacement string.

A simple version for you case would be:

vietnamese_map = {
    ord(u'ư'): 'u',
    ord(u'ơ'): 'o',
    ord(u'á'): 'a',
    ord(u'n'): 'n',
    ord(u'h'): 'h',
    ord(u'ữ'): 'u',
    ord(u'n'): 'n',
    ord(u'g'): 'g',
    ord(u'v'): 'v',
    ord(u'i'): 'i',
    ord(u'ê'): 'e',
    ord(u'n'): 'n',
    ord(u'k'): 'k',
    ord(u'ẹ'): 'e',
    ord(u'o'): 'o',
}

And then you can call:

print u"những-viên-kẹo".translate(vietnamese_map)

To get:

u"nhung-vien-keo"

For more advanced use (ie a dynamic dict), see eg http://effbot.org/zone/unicode-convert.htm

Note that the above is just to show you what the map needs to look like, it's not a particularly convenient way of entering the data. A more convenient way to do the exact same thing is something like:

_map = u"nn hh ữu nn gg vv ii êe nn kk ẹe oo"
# Take the above string and generate a translation dict
vietnamese_map = dict((ord(m[0]), m[1:]) for m in _map.split())
print u"những-viên-kẹo".translate(vietnamese_map)


You can try normalize it Python ->

http://pyright.blogspot.com/2009/11/unicode-normalization-python-3x-unicode.html

this could help instead of retype the vietnamese alphabet from a á ớ bờ cờ dờ đờ and ignore the possibility of others special latin character, just run a normalization function, and test if everything work well, remember to test the word "đ" since I've encountered the problem that the normalization function did not normalize Đ - D.

Good luck :P


You should write a new filter or tag to do that.


Or you can just pull in this app to do it for you.

https://github.com/un33k/django-uslug

It also guarantees uniqueness.

from uslug import uSlug
MyModel(models.Model):
    title = models.CharField(max_length=255)
    slug  = models.SlugField(blank=True)

    def save(self, *args, **kwargs):
        if not self.slug:
            self.slug = uSlug(self.title)
        super(MyModel, self).save(*args, **kwargs)


I will post the complete vietnamese map here for any fellows who need it. The map also have CAPITALS so your text can retain its CaPiTalized form

vietnamese_map = {
    # Lower
    ord(u'ò'): 'o', ord(u'ó'): 'o', ord(u'ỏ'): 'o', ord(u'õ'): 'o', ord(u'ọ'): 'o',
    ord(u'ơ'): 'o',
    ord(u'ờ'): 'o', ord(u'ớ'): 'o', ord(u'ở'): 'o', ord(u'ỡ'): 'o', ord(u'ợ'): 'o',
    ord(u'ô'): 'o',
    ord(u'ồ'): 'o', ord(u'ố'): 'o', ord(u'ổ'): 'o', ord(u'ỗ'): 'o', ord(u'ộ'): 'o',

    ord(u'à'): 'a', ord(u'á'): 'a', ord(u'ả'): 'a', ord(u'ã'): 'a', ord(u'ạ'): 'a',
    ord(u'ă'): 'a',
    ord(u'ằ'): 'a', ord(u'ắ'): 'a', ord(u'ẳ'): 'a', ord(u'ẵ'): 'a', ord(u'ặ'): 'a',
    ord(u'â'): 'a',
    ord(u'ầ'): 'a', ord(u'ấ'): 'a', ord(u'ẩ'): 'a', ord(u'ẫ'): 'a', ord(u'ậ'): 'a',

    ord(u'đ'): 'd',

    ord(u'è'): 'e', ord(u'é'): 'e', ord(u'ẻ'): 'e', ord(u'ẽ'): 'e', ord(u'ẹ'): 'e',
    ord(u'ê'): 'e',
    ord(u'ề'): 'e', ord(u'ế'): 'e', ord(u'ể'): 'e', ord(u'ễ'): 'e', ord(u'ệ'): 'e',

    ord(u'ì'): 'i', ord(u'í'): 'i', ord(u'ỉ'): 'i', ord(u'ĩ'): 'i', ord(u'ị'): 'i',
    ord(u'ù'): 'u', ord(u'ú'): 'u', ord(u'ủ'): 'u', ord(u'ũ'): 'u', ord(u'ụ'): 'u',
    ord(u'ư'): 'u',
    ord(u'ừ'): 'u', ord(u'ứ'): 'u', ord(u'ử'): 'u', ord(u'ữ'): 'u', ord(u'ự'): 'u',
    ord(u'ỳ'): 'y', ord(u'ý'): 'y', ord(u'ỷ'): 'y', ord(u'ỹ'): 'y', ord(u'ỵ'): 'y',

    # CAPITAL
    ord(u'Ò'): 'O', ord(u'Ó'): 'O', ord(u'Ỏ'): 'O', ord(u'Õ'): 'O', ord(u'Ọ'): 'O',
    ord(u'Ơ'): 'O',
    ord(u'Ờ'): 'O', ord(u'Ớ'): 'O', ord(u'Ở'): 'O', ord(u'Ỡ'): 'O', ord(u'Ợ'): 'O',
    ord(u'Ô'): 'O',
    ord(u'Ồ'): 'O', ord(u'Ố'): 'O', ord(u'Ổ'): 'O', ord(u'Ỗ'): 'O', ord(u'Ộ'): 'O',

    ord(u'À'): 'A', ord(u'Á'): 'A', ord(u'Ả'): 'A', ord(u'Ã'): 'A', ord(u'Ạ'): 'A',
    ord(u'Ă'): 'A',
    ord(u'Ằ'): 'A', ord(u'Ắ'): 'A', ord(u'Ẳ'): 'A', ord(u'Ẵ'): 'A', ord(u'Ặ'): 'A',
    ord(u'Â'): 'A',
    ord(u'Ầ'): 'A', ord(u'Ấ'): 'A', ord(u'Ẩ'): 'A', ord(u'Ẫ'): 'A', ord(u'Ậ'): 'A',

    ord(u'Đ'): 'D',

    ord(u'È'): 'E', ord(u'É'): 'E', ord(u'Ẻ'): 'E', ord(u'Ẽ'): 'E', ord(u'Ẹ'): 'E',
    ord(u'Ê'): 'E',
    ord(u'Ề'): 'E', ord(u'Ế'): 'E',  ord(u'Ể'): 'E', ord(u'Ễ'): 'E', ord(u'Ệ'): 'E',

    ord(u'Ì'): 'I', ord(u'Í'): 'I', ord(u'Ỉ'): 'I', ord(u'Ĩ'): 'I', ord(u'Ị'): 'I',
    ord(u'Ù'): 'U', ord(u'Ú'): 'U', ord(u'Ủ'): 'U', ord(u'Ũ'): 'U', ord(u'Ụ'): 'U',
    ord(u'Ư'): 'U',
    ord(u'Ừ'): 'U', ord(u'Ứ'): 'U', ord(u'Ử'): 'U', ord(u'Ữ'): 'U', ord(u'Ự'): 'U',
    ord(u'Ỳ'): 'Y', ord(u'Ý'): 'Y', ord(u'Ỷ'): 'Y', ord(u'Ỹ'): 'Y', ord(u'Ỵ'): 'Y',
}
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜