添加链接
link管理
链接快照平台
  • 输入网页链接,自动生成快照
  • 标签化管理网页链接
QT 翻译文件虽然可以使用linguist.exe进行翻译,但是这个比较专业,复杂,不太适合把它直接提供给客户进行翻译,而该例子是则讲述如何将QT翻译文件.ts文件转换成excel文件,得到excel文件后可将之提供给客户翻译,之后再讲翻译好的excel文件转换成.ts文件.

我们的 目的是将.ts翻译文件与excel文件相互转换 ,.ts是xml格式的,所以我们需要使用Qt的解析XML相关的几个类和解析excel文件相关的几个类,它们分别是:

QDomDocument
QDomElement
QDomNode
QDomText
QDomNodeList
QAxObject


一. 运行结果

image.png


二. 将Ts转换成excel实现过程

1. 创建QDomDocument对象

    QFile file( m_tsPath );
    if( !file.open( QFile::ReadOnly | QFile::Text  ) )  //打开.ts文件
        qDebug() << QObject::tr("error::ParserXML->OpenXmlFile->file.open->%s\n") << tsPath();
        return false;
    QDomDocument t_doc;
    if( !t_doc.setContent( &file ) )
        qDebug() << QObject::tr("error::ParserXML->OpenXmlFile->doc.setContent\n") << tsPath();
        file.close();
        return false;
    }


2. 读取ts文件中的内容到QHash容器中

   QDomElement root = t_doc.documentElement();
   QDomNode n = root.firstChild();
   while ( !n.isNull() )
       QDomElement e = n.toElement();
       if( !e.isNull())
           if( e.nodeName() == "context" )
               QDomNodeList list = e.childNodes(); //获得元素e的所有子节点的列表
               for(int a=0; a<list.count(); a++) //遍历该列表
                   QDomNode node = list.at(a);
                   if(node.isElement())
                       if( node.nodeName() == "message" )
                           QDomNodeList list2 = node.childNodes(); //获得元素node的所有子节点的列表
                           QString curText;
                           for(int i=0; i<list2.count(); i++) //遍历该列表
                               QDomNode node2 = list2.at(i);
                               if(node2.isElement())
                                   if( node2.nodeName() == "source" )
                                       curText = node2.firstChild().toText().data();
                                   else if( node2.nodeName() == "translation" )
                                       if (isDigitStr(curText) || curText.isEmpty() || curText.startsWith("ID_") || curText.endsWith("_ID") \
                                               || (curText.endsWith("Form") && curText.length() > 4))
                                       else if (m_excludeVector.contains(curText))
                                           languageHash.insert(curText, node2.firstChild().toText().data());
                       else if( node.nodeName() == "name" )
       n = n.nextSibling();
    }


3. 打开excel文件,打开对应的sheet

    QAxObject excel("Excel.Application");//连接Excel控件
    excel.setProperty("Visible", false);// 不显示窗体
    excel.setProperty("DisplayAlerts", false); //不显示任何警告信息。如果为true, 那么关闭时会出现类似"文件已修改,是否保存"的提示
    QAxObject* workbooks = excel.querySubObject("WorkBooks"); // 获取工作簿集合
    if (!workbooks)
        return false;
    workbooks->dynamicCall("Add"); // 新建一个工作簿
    QAxObject* workbook = excel.querySubObject("ActiveWorkBook"); // 获取当前工作簿
    if (!workbook)
        return false;
    QAxObject* worksheet = workbook->querySubObject("WorkSheets(int)", 1); // 获取工作表集合的工作表1, 即sheet1
    if (!worksheet)
        return false;
    }


4. 保存QHash容器中的内容到Excel中

    QAxObject* cell = NULL;
    int rowCount = 1;
    QHashIterator<QString, QString> iter(languageHash);
    while(iter.hasNext())
        iter.next();
        cell = worksheet->querySubObject("Cells(int, int)", rowCount, 1);
        if (cell)
            cell->dynamicCall("SetValue(conts QVariant&)", iter.key()); // 设置单元格的值
        cell = worksheet->querySubObject("Cells(int, int)", rowCount, 2);
        if (cell)
            cell->dynamicCall("SetValue(conts QVariant&)", iter.value()); // 设置单元格的值
        rowCount++;
    workbook->dynamicCall("SaveAs(const QString&)", QDir::toNativeSeparators(m_excelPath)); //保存到filepath // 注意一定要用QDir::toNativeSeparators, 将路径中的"/"转换为"\", 不然一定保存不了
    workbook->dynamicCall("Close (Boolean)", false);  //关闭文件
    excel.dynamicCall("Quit(void)");  //退出


三. 使用excel打开第二步得到的文件,并将翻译结果写在第二列


四. 将Excel文档转换成ts文件

1. 打开excel文档,这与2.3相同,在这里不再重复介绍

2.获取Excel文档的内容,保存到QHash容器中

    QAxObject* cell = NULL;
    QString source;
    QString dest;
    for(int i=intRowStart;i<intRow+intRowStart;i++)
        cell = worksheet->querySubObject("Cells(int, int)", i, 1);  //获单元格值
        source = cell->dynamicCall("Value2()").toString();
        cell = worksheet->querySubObject("Cells(int, int)", i, 2);  //获单元格值
        dest = cell->dynamicCall("Value2()").toString();
        languageHash.insert(source, dest);
    }

3.打开ts文件,这一步与2.1相同

4. 保存QHash容器中的内容到ts文件中

    QDomElement root = t_doc.documentElement();
    QDomNode n = root.firstChild();
    while ( !n.isNull() )
       QDomElement e = n.toElement();
       if( !e.isNull())
           if( e.nodeName() == "context" )
               QDomNodeList list = e.childNodes(); //获得元素e的所有子节点的列表
               for(int a=0; a<list.count(); a++) //遍历该列表
                   QDomNode node = list.at(a);
                   if(node.isElement())
                       if( node.nodeName() == "message" )
                           QDomNodeList list2 = node.childNodes(); //获得元素node的所有子节点的列表
                           QString curText;
                           for(int i=0; i<list2.count(); i++) //遍历该列表
                               QDomNode node2 = list2.at(i);
                               if(node2.isElement())
                                   if( node2.nodeName() == "source" )
                                       curText = node2.firstChild().toText().data();
                                   else if( node2.nodeName() == "translation" )
                                       if (languageHash.contains(curText) && !languageHash.value(curText).isEmpty())
                                           if (node2.hasChildNodes())
                                               QDomNode oldNode = node2.firstChild();
                                               node2.firstChild().setNodeValue(languageHash.value(curText));
                                               QDomNode newNode = node2.firstChild();
                                               node2.replaceChild(newNode, oldNode);
                                               QDomElement e = node2.toElement();
                                               e.removeAttribute("type");
                                               QDomText newNode;
                                               newNode = t_doc.createTextNode(languageHash.value(curText));
                                               node2.appendChild(newNode);
                       else if( node.nodeName() == "name" )
       n = n.nextSibling();
    if(!file.open(QFile::WriteOnly|QFile::Truncate))
        return ;
    QTextStream ts(&file);
    ts.reset();
    ts.setCodec("utf-8");
    t_doc.save(ts, 4, QDomNode::EncodingFromTextStream);
    file.close();


五. 项目结构图

image.png


六. 使用介绍

选择好相应的.ts文件和excel文件,exclue file则是一些不想要翻译的文字的集合,可以是一个空文件,选好文件之后,点击ts to excel按钮,得到excel文件,然后可以在excel中进行翻译,将翻译结果写在excel文档的第二列,翻译完成后,点击excel to ts按钮,将excel文件转换成.ts文件。.ts文件放到相应的qt项目中,使用qt语言家生产.qm文件就可以在程序中使用。