rótulos e traduções Django - Modelo de Design

votos
2

Vamos dizer que eu tenho o seguinte modelo de Django:

class StandardLabel(models.Model):
    id = models.AutoField(primary_key=True)
    label = models.CharField(max_length=255)
    abbreviation = models.CharField(max_length=255)

Cada etiqueta possui um número de identificação, o texto da etiqueta, e uma abreviatura. Agora, eu quero ter esses rótulos traduzíveis para outras línguas. Qual é a melhor maneira de fazer isso?

A meu ver, tenho algumas opções:

1: Adicione as traduções como campos no modelo:

class StandardLabel(models.Model):
    id = models.AutoField(primary_key=True)
    label_english = models.CharField(max_length=255)
    abbreviation_english = models.CharField(max_length=255)
    label_spanish = models.CharField(max_length=255)
    abbreviation_spanish = models.CharField(max_length=255)

Isso obviamente não é ideal - a adição de idiomas requer a edição do modelo, o nome do campo correto depende do idioma.

2: Adicionar a língua como uma chave estrangeira:

class StandardLabel(models.Model):
    id = models.AutoField(primary_key=True)
    label = models.CharField(max_length=255)
    abbreviation = models.CharField(max_length=255)
    language = models.ForeignKey('languages.Language')

Isto é muito melhor, agora eu posso pedir para todas as etiquetas com uma certa linguagem, e jogá-los em um dicionário:

labels = StandardLabel.objects.filter(language=1)
labels = dict((x.pk, x) for x in labels)

Mas o problema aqui é que os rótulos dict pretende ser uma tabela de pesquisa, assim:

x = OtherObjectWithAReferenceToTheseLabels.object.get(pk=3)
thelabel = labels[x.labelIdNumber].label

Que não funciona se houver uma linha por etiqueta, possivelmente com vários idiomas para um único rótulo. Para solucionar esse, eu preciso de outro campo:

class StandardLabel(models.Model):
    id = models.AutoField(primary_key=True)
    group_id = models.IntegerField(db_index=True)
    label = models.CharField(max_length=255)
    abbreviation = models.CharField(max_length=255)
    language = models.ForeignKey('languages.Language')
    class Meta:
        unique_together=((group_id, language),)
#and I need to group them differently:
labels = StandardLabel.objects.filter(language=1)
labels = dict((x.group_id, x) for x in labels)

rótulo de texto jogar fora em um novo modelo: 3:

class StandardLabel(models.Model):
    id = models.AutoField(primary_key=True)
    text = models.ManyToManyField('LabelText')

class LabelText(models.Model):
    id = models.AutoField(primary_key=True)
    label = models.CharField(max_length=255)
    abbreviation = models.CharField(max_length=255)
    language = models.ForeignKey('languages.Language')

labels = StandardLabel.objects.filter(text__language=1)
labels = dict((x.pk, x) for x in labels)

Mas então isso não funcionar, e faz com que um banco de dados atingido cada vez que faz referência o texto do rótulo:

x = OtherObjectWithAReferenceToTheseLabels.object.get(pk=3)
thelabel = labels[x.labelIdNumber].text.get(language=1)

Eu tenho implementado a opção 2, mas acho que é muito feio - eu não gosto do campo group_id, e eu não consigo pensar em nada melhor para nomeá-lo. Além disso, StandardLabel como eu estou usando é um modelo abstrato, que eu subclasse para obter diferentes conjuntos de etiquetas para diferentes campos.

Suponho que, se a opção 3 / não / bater o banco de dados, é o que eu escolheria. Eu acredito que o verdadeiro problema é que o filtro text__language=1não armazena em cache os LabelTextcasos, e por isso o DB é atingido quando eutext.get(language=1)

Quais são seus pensamentos sobre isso? Alguém pode recomendar uma solução mais limpa?

Editar : Só para deixar claro, estes não são formar rótulos, de modo que o sistema de Django Internacionalização não ajuda.

Publicado 05/03/2009 em 20:09
fonte usuário
Em outras línguas...                            


4 respostas

votos
3

Outra opção que você pode considerar, dependendo do seu design do aplicativo é claro, é fazer uso de recursos de internacionalização do Django. A abordagem que eles usam é bastante comum a abordagem encontrada no software desktop.

Eu vejo a questão foi editado para adicionar uma referência a Django internacionalização, assim que você sabe sobre ele, mas as características Intl em Django se aplicam a muito mais do que apenas formas; ele touchs bastante, e precisa apenas de alguns ajustes para seu projeto aplicativo.

Seus docs aqui: http://docs.djangoproject.com/en/dev/topics/i18n/#topics-i18n

A idéia é que você define o seu modelo como se houvesse apenas um idioma. Em outras palavras, não fazem referência à linguagem em tudo, e colocar apenas, digamos, Inglês no modelo.

Assim:

class StandardLabel(models.Model):
    abbreviation = models.CharField(max_length=255)
    label = models.CharField(max_length=255)

Eu sei que isso parece que você totalmente jogado para fora da questão da língua, mas você realmente apenas mudou-lo. Em vez da língua estar em seu modelo de dados, você empurrou-o para a vista.

As características django internacionalização permitem a geração de arquivos de tradução de texto, e fornece uma série de recursos para puxar texto fora do sistema em arquivos. Isso é realmente muito útil porque permite que você envie arquivos simples para o seu tradutor, o que torna seu trabalho mais fácil. Adicionando uma nova língua é tão fácil como obter o arquivo traduzido em um novo idioma.

Os arquivos de tradução definir o rótulo do banco de dados, e uma tradução para esse idioma. Há funções para a manipulação da tradução dinamicamente em tempo de execução para os modelos, visualizações admin, javascript, e modelos.

Por exemplo, em um modelo, você pode fazer algo como:

<b>Hello {% trans "Here's the string in english" %}</b>

Ou em código vista, você pode fazer:

# See docs on setting language, or getting Django to auto-set language
s = StandardLabel.objects.get(id=1)
lang_specific_label = ugettext(s.label)

Claro, se seu aplicativo é toda sobre a entrada em novos idiomas on the fly, então esta abordagem pode não funcionar para você. Ainda assim, ter um olhar para o projeto de internacionalização como você pode tanto ser capaz de usá-lo "como está", ou seja inspirado a uma solução django-apropriado que funciona para o seu domínio.

Respondeu 05/03/2009 em 20:51
fonte usuário

votos
2

Gostaria de manter as coisas o mais simples possível. A pesquisa será o código mais limpo com algo parecido com isso mais rápido e:

class StandardLabel(models.Model):
    abbreviation = models.CharField(max_length=255)
    label = models.CharField(max_length=255)
    language = models.CharField(max_length=2)
    # or, alternately, specify language as a foreign key:
    #language = models.ForeignKey(Language)

    class Meta:
        unique_together = ('language', 'abbreviation')

Em seguida, consulta com base na abreviação e idioma:

l = StandardLabel.objects.get(language='en', abbreviation='suite')
Respondeu 05/03/2009 em 20:38
fonte usuário

votos
1

Eu prefiro muito mais para adicionar um campo para cada língua do que uma nova instância do modelo por língua. Ele requer alteração de esquema quando você adicionar um novo idioma, mas isso não é difícil, e quantas vezes você espera para adicionar idiomas? Nesse meio tempo, ele vai dar-lhe um melhor desempenho do banco de dados (sem adição de junta ou índices) e você não tem que estragar a sua lógica de consulta com o material de tradução; manter tudo nos modelos onde pertence.

Mesmo melhor, usar um aplicativo reutilizável como Django-transmeta ou django-modeltranslation que torna este simples estúpido e quase completamente transparente.

Respondeu 06/03/2009 em 20:26
fonte usuário

votos
0

Embora eu iria com solução de Daniel , aqui é uma alternativa a partir do que eu entendi de seus comentários:

Você pode usar um XMLField ou JSONField para armazenar seus pares idioma / tradução. Isso permitiria que seus objetos referenciar a sua rótulos para usar um único idpara todas as traduções. E então você pode ter um método gerente de costume para chamar uma tradução específica:

Label.objects.get_by_language('ru', **kwargs)

Ou uma solução ligeiramente mais limpo e um pouco mais complicado que joga bem com adminseria desnormalizar o XMLField para outro modelo com muitos-para-um relacionamento com a Labelmodelo. Mesma API, mas em vez de analisar XML poderia consultar os modelos relacionados.

Para ambas as sugestões não há um único objeto onde os usuários de uma etiqueta irá apontar para.

Eu não me preocuparia com as consultas demais, Django armazena em cache consultas e seu DBMS provavelmente teria caching superiores lá também.

Respondeu 05/03/2009 em 22:30
fonte usuário

Cookies help us deliver our services. By using our services, you agree to our use of cookies. Learn more