mirror of
https://github.com/strapi/strapi.git
synced 2025-12-26 14:44:31 +00:00
Merge branch 'master' into eslint
This commit is contained in:
commit
c09f5138a2
8
.github/CONTRIBUTING.md
vendored
Executable file → Normal file
8
.github/CONTRIBUTING.md
vendored
Executable file → Normal file
@ -34,6 +34,9 @@ To facilitate the contribution, we drastically reduce the amount of commands nec
|
||||
|
||||
> Note: If the installation failed, please remove the global packages related to Strapi. The command `npm ls strapi` will help you to find where your packages are installed globally.
|
||||
|
||||
> Note: You can run `npm run setup:build` to build the plugins' admin (the setup time will be longer).
|
||||
|
||||
|
||||
The development environment has been installed. Now, you have to create a development project to live-test your updates.
|
||||
|
||||
1. Go to a folder on your computer `cd /path/to/my/folder`.
|
||||
@ -43,8 +46,9 @@ The development environment has been installed. Now, you have to create a develo
|
||||
Awesome! You are now able to make bug fixes or enhancements in the framework layer of Strapi. **To make updates in the administration panel, you need to go a little bit further.**
|
||||
|
||||
4. Open a new tab or new terminal window.
|
||||
5. Go to the `/admin` folder of your currently running app.
|
||||
6. Run `npm start` and go to the following url [http://localhost:4000/admin](http://localhost:4000/admin)
|
||||
5. Link the `strapi-helper-plugin` into the `analytics` plugin : `cd my-app/plugins/analytics && npm link strapi-helper-plugin`.
|
||||
6. Go to the `my-app/admin` folder of your currently running app.
|
||||
7. Run `npm start` and go to the following url [http://localhost:4000/admin](http://localhost:4000/admin)
|
||||
|
||||
### Plugin Development Setup
|
||||
|
||||
|
||||
33
.github/ISSUE_TEMPLATE.md
vendored
Executable file → Normal file
33
.github/ISSUE_TEMPLATE.md
vendored
Executable file → Normal file
@ -1,12 +1,15 @@
|
||||
<!-- Chose BUG or FEATURE REQUEST template and delete the one you don't use-->
|
||||
<!-- ⚠️ Don't forgot the checkbox at the end of your issue -->
|
||||
<!--
|
||||
⚠️ If you do not respect these two points, your issue will be closed.
|
||||
- Don't forget the checkbox at the end of your issue.
|
||||
- Respect this template.
|
||||
-->
|
||||
|
||||
*BUG TEMPLATE* <!-- Delete this header from your issue -->
|
||||
*BUG TEMPLATE* <!-- Delete this header from your issue. -->
|
||||
|
||||
<!-- ⚠️ Before writing your issue make sure you are using :-->
|
||||
<!-- Node 9.x.x -->
|
||||
<!-- npm 5.x.x -->
|
||||
<!-- The latest version of Strapi -->
|
||||
<!-- The latest version of Strapi. -->
|
||||
|
||||
**Informations**
|
||||
- **Node.js version**:
|
||||
@ -15,22 +18,38 @@
|
||||
- **Database**:
|
||||
- **Operating system**:
|
||||
|
||||
|
||||
**What is the current behavior?**
|
||||
|
||||
|
||||
|
||||
**Steps to reproduce the problem**
|
||||
|
||||
|
||||
|
||||
**What is the expected behavior?**
|
||||
|
||||
|
||||
|
||||
**Suggested solutions**
|
||||
|
||||
|
||||
|
||||
---
|
||||
|
||||
*FEATURE REQUEST TEMPLATE* <!-- Delete this header from your issue -->
|
||||
*FEATURE REQUEST TEMPLATE* <!-- Delete this header from your issue. -->
|
||||
|
||||
**What is the expected behavior?**
|
||||
|
||||
|
||||
|
||||
---
|
||||
|
||||
- [ ] I'm sure that this issue hasn't already been referenced
|
||||
<!-- ⬆️ Don't delete this checkbox from your issue and approve it. -->
|
||||
<!-- ⚠️ Make sure to browse the opened and closed issues. -->
|
||||
|
||||
- [ ] I'm sure that this feature hasn't already been referenced
|
||||
|
||||
<!--
|
||||
⬆️ Don't delete this checkbox from your issue and approve it.
|
||||
Add an `x` -> [x] or click on the checkbox when your issue is created.
|
||||
-->
|
||||
|
||||
50
.github/ISSUE_TEMPLATE/BUG_REPORT.md
vendored
Normal file
50
.github/ISSUE_TEMPLATE/BUG_REPORT.md
vendored
Normal file
@ -0,0 +1,50 @@
|
||||
---
|
||||
name: 🐛 Bug Report
|
||||
about: Create a report to help us improve 🤔.
|
||||
---
|
||||
|
||||
<!--
|
||||
⚠️ If you do not respect these two points, your issue will be closed.
|
||||
- Don't forget the checkbox at the end of your issue.
|
||||
- Respect this template.
|
||||
-->
|
||||
|
||||
<!-- ⚠️ Before writing your issue make sure you are using:-->
|
||||
<!-- Node 9.x.x -->
|
||||
<!-- npm 5.x.x -->
|
||||
<!-- The latest version of Strapi. -->
|
||||
|
||||
**Informations**
|
||||
- **Node.js version**:
|
||||
- **npm version**:
|
||||
- **Strapi version**:
|
||||
- **Database**:
|
||||
- **Operating system**:
|
||||
|
||||
|
||||
**What is the current behavior?**
|
||||
|
||||
|
||||
|
||||
**Steps to reproduce the problem**
|
||||
|
||||
|
||||
|
||||
**What is the expected behavior?**
|
||||
|
||||
|
||||
|
||||
**Suggested solutions**
|
||||
|
||||
|
||||
|
||||
---
|
||||
|
||||
<!-- ⚠️ Make sure to browse the opened and closed issues. -->
|
||||
|
||||
- [ ] I'm sure that this feature hasn't already been referenced.
|
||||
|
||||
<!--
|
||||
⬆️ Don't delete this checkbox from your issue and approve it.
|
||||
Add an `x` -> [x] or click on the checkbox when your issue is created.
|
||||
-->
|
||||
25
.github/ISSUE_TEMPLATE/FEATURE_REQUEST.md
vendored
Normal file
25
.github/ISSUE_TEMPLATE/FEATURE_REQUEST.md
vendored
Normal file
@ -0,0 +1,25 @@
|
||||
---
|
||||
name: 🚀 Feature Request
|
||||
about: Suggest an idea for this project 💡!
|
||||
---
|
||||
|
||||
<!--
|
||||
⚠️ If you do not respect these two points, your issue will be closed.
|
||||
- Don't forget the checkbox at the end of your issue.
|
||||
- Respect this template.
|
||||
-->
|
||||
|
||||
**What is the expected behavior?**
|
||||
|
||||
|
||||
|
||||
---
|
||||
|
||||
<!-- ⚠️ Make sure to browse the opened and closed issues. -->
|
||||
|
||||
- [ ] I'm sure that this issue hasn't already been referenced.
|
||||
|
||||
<!--
|
||||
⬆️ Don't delete this checkbox from your issue and approve it.
|
||||
Add an `x` -> [x] or click on the checkbox when your issue is created.
|
||||
-->
|
||||
17
.github/PULL_REQUEST_TEMPLATE.md
vendored
Executable file → Normal file
17
.github/PULL_REQUEST_TEMPLATE.md
vendored
Executable file → Normal file
@ -0,0 +1,17 @@
|
||||
<!-- ⚠️ Your PR title will appear in the changelogs please make it short detailed and understandable for all. -->
|
||||
|
||||
<!-- Uncomment the correct contribution type. !-->
|
||||
|
||||
My PR is a:
|
||||
<!-- 💥 Breaking change -->
|
||||
<!-- 🐛 Bug fix -->
|
||||
<!-- 💅 Enhancement -->
|
||||
<!-- 🚀 New feature -->
|
||||
|
||||
Main update on the:
|
||||
<!-- Admin -->
|
||||
<!-- Documentation -->
|
||||
<!-- Framework -->
|
||||
<!-- Plugin -->
|
||||
|
||||
<!-- Write a short description of what your PR does and link the concerned issues of your update. -->
|
||||
130
CONTRIBUTING.md
130
CONTRIBUTING.md
@ -1,130 +0,0 @@
|
||||
# Contribute to the project
|
||||
|
||||
Strapi is an open-source project administered by [the Strapi team](http://strapi.io).
|
||||
|
||||
We welcome and encourage everyone who want to help us on Strapi.
|
||||
|
||||
Before contributing, ensure that your effort is aligned with the project's roadmap by talking to the maintainers, especially if you are going to spend a lot of time on it. Feel free to [join us on Slack](http://slack.strapi.io) if you are interested in helping us or [drop us an email](mailto:hi@strapi.io) if you are interested in working with us.
|
||||
|
||||
### Open Development & Community Driven
|
||||
Strapi is open-source under the [MIT license](https://github.com/strapi/strapi/blob/master/LICENSE.md). All the work done is available on GitHub.
|
||||
The core team and the contributors send pull requests which go through the same validation process.
|
||||
|
||||
Every user can send a feature request using the [issues](https://github.com/strapi/strapi/issues) on GitHub.
|
||||
|
||||
|
||||
### Repository Organization
|
||||
We made the choice to use a monorepo design such as [React](https://github.com/facebook/react/tree/master/packages), [Babel](https://github.com/babel/babel/tree/master/packages), [Meteor](https://github.com/meteor/meteor/tree/devel/packages) or [Ember](https://github.com/emberjs/ember.js/tree/master/packages) do. It allows the community to easily maintain the whole ecosystem up-to-date and consistent.
|
||||
|
||||
The Babel team wrotes an excellent short post about [the pros and cons of the monorepo design](https://github.com/babel/babel/blob/master/doc/design/monorepo.md).
|
||||
|
||||
We will do our best to keep the master branch clean as possible, with tests passing all the times. However, it can happen that the master branch moves faster than the release cycle. To ensure to use the latest stable version, please refers to the [release on npm](https://www.npmjs.com/package/strapi).
|
||||
|
||||
If you send a pull request, please do it again the `master` branch. We are developing upcoming versions separately to ensure non-breaking changes from master to the latest stable major version.
|
||||
|
||||
|
||||
### Setup Development Environment
|
||||
To facilitate the contribution, we drastically reduce the amount of commands necessary to install the entire development environment. First of all, you need to check if you're using the recommended versions of Node.js (v8) and npm (v5).
|
||||
|
||||
**Then, please follow the instructions below:**
|
||||
|
||||
1. [Fork the repository](https://github.com/strapi/strapi) to your own GitHub account.
|
||||
2. Clone it to your computer `git clone git@github.com:strapi/strapi.git`.
|
||||
3. Run `npm run setup` at the root of the directory.
|
||||
|
||||
> Note: If the installation failed, please remove the global packages related to Strapi. The command `npm ls strapi` will help you to find where your packages are installed globally.
|
||||
|
||||
The development environment has been installed. Now, you have to create a development project to live-test your updates.
|
||||
|
||||
1. Go to a folder on your computer `cd /path/to/my/folder`.
|
||||
2. Create a new project `strapi new myDevelopmentProject --dev`.
|
||||
3. Start your app with `strapi start`.
|
||||
|
||||
Awesome! You are now able to make bug fixes or enhancements in the framework layer of Strapi. **To make updates in the administration panel, you need to go a little bit further.**
|
||||
|
||||
4. Open a new tab or new terminal window.
|
||||
5. Go to the `/admin` folder of your currently running app.
|
||||
6. Run `npm start` and go to the following url [http://localhost:4000/admin](http://localhost:4000/admin)
|
||||
|
||||
### Plugin Development Setup
|
||||
|
||||
To create a new plugin, you'll have to run the following commands
|
||||
|
||||
1. In your project folder `cd myDevelopmentProject && strapi generate:plugin my-plugin`.
|
||||
2. Make sure that the `strapi-helper-plugin` is linked to your plugin
|
||||
- In the folder where strapi is cloned `cd pathToStrapiRepo/strapi/packages/strapi-helper-plugin && npm link`.
|
||||
- In your project folder `cd pathToMyProject/myDevelopmentProject/plugins/my-plugin && npm link strapi-helper-plugin`.
|
||||
3. Start the server in the admin folder `cd pathToMyProject/myDevelopmentProject/admin && npm start` and go to the following url [http://localhost:4000/admin](http://localhost:4000/admin).
|
||||
|
||||
***
|
||||
|
||||
## Maintainers
|
||||
|
||||
- Aurélien Georget ([@aurelsicoko](https://github.com/aurelsicoko)) (Strapi)
|
||||
- Jim Laurie ([@lauriejim](https://github.com/lauriejim)) (Strapi)
|
||||
- Pierre Burgy ([@pierreburgy](https://github.com/pierreburgy)) (Strapi)
|
||||
- Cyril Lopez ([@soupette](https://github.com/soupette)) (Strapi)
|
||||
|
||||
The Strapi team have npm publishing rights for modules and also has the final say on releasing new versions.
|
||||
|
||||
***
|
||||
|
||||
## Reporting an issue
|
||||
|
||||
Before reporting an issue you need to make sure:
|
||||
- You are experiencing a concrete technical issue with Strapi (ideas and feature proposals should happen [on Slack](http://slack.strapi.io)).
|
||||
- You are not asking a question about how to use Strapi or about whether or not Strapi has a certain feature. For general help using Strapi, please refer to [the official Strapi documentation](http://strapi.io). For additional help, ask a question on [StackOverflow](http://stackoverflow.com/questions/tagged/strapi).
|
||||
- You have already searched for related [issues](https://github.com/strapi/strapi/issues), and found none open (if you found a related _closed_ issue, please link to it in your post).
|
||||
- Your issue title is concise, on-topic and polite.
|
||||
- You can provide steps to reproduce this issue that others can follow.
|
||||
- You have tried all the following (if relevant) and your issue remains:
|
||||
- Make sure you have the right application started.
|
||||
- Make sure you've killed the Strapi server with CTRL+C and started it again.
|
||||
- Make sure you closed any open browser tabs pointed at `localhost` before starting Strapi.
|
||||
- Make sure you do not have any other Strapi applications running in other terminal windows.
|
||||
- Make sure the application you are using to reproduce the issue has a clean `node_modules` directory, meaning:
|
||||
* no dependencies are linked (e.g. you haven't run `npm link`)
|
||||
* that you haven't made any inline changes to files in the `node_modules` folder
|
||||
* that you don't have any weird global dependency loops. The easiest way to double-check any of the above, if you aren't sure, is to run: `$ rm -rf node_modules && npm cache clear && npm install`.
|
||||
|
||||
***
|
||||
|
||||
## Code of Conduct
|
||||
|
||||
[The Strapi team](https://strapi.io/company) is committed to fostering a welcoming community for Strapi. If you encounter any unacceptable behavior, follow these steps to report the issue to the team. We are here to help.
|
||||
|
||||
### Our Pledge
|
||||
|
||||
In the interest of fostering an open and welcoming environment, we pledge to making participation in our project and our community a harassment-free experience for everyone, regardless of age, body size, disability, ethnicity, gender identity and expression, level of experience, nationality, personal appearance, race, religion, or sexual identity and orientation.
|
||||
|
||||
### Our Standards
|
||||
|
||||
Examples of behavior that contributes to creating a positive environment include:
|
||||
- Using welcoming and inclusive language
|
||||
- Being respectful of differing viewpoints and experiences
|
||||
- Gracefully accepting constructive criticism
|
||||
- Focusing on what is best for the community
|
||||
- Showing empathy towards other community members
|
||||
|
||||
Examples of unacceptable behavior by participants include:
|
||||
- The use of sexualized language or imagery and unwelcome sexual attention or advances
|
||||
- Trolling, insulting/derogatory comments, and personal or political attacks
|
||||
- Public or private harassment
|
||||
- Publishing others' private information, such as a physical or electronic address, without explicit permission
|
||||
- Other conduct which could reasonably be considered inappropriate in a professional setting
|
||||
|
||||
### Our responsibilities
|
||||
|
||||
The Strapi team is responsible for clarifying the standards of acceptable behavior and is expected to take appropriate and fair corrective action in response to any instances of unacceptable behavior.
|
||||
|
||||
The Strapi team has the right and responsibility to remove, edit, or reject comments, commits, code, wiki edits, issues, and other contributions that are not aligned to this Code of Conduct, or to ban temporarily or permanently any contributor for other behaviors that they deem inappropriate, threatening, offensive, or harmful.
|
||||
|
||||
### Scope
|
||||
|
||||
This Code of Conduct applies both within project spaces and in public spaces when an individual is representing the project or its community. Examples of representing a project or community include using an official project e-mail address, posting via an official social media account, or acting as an appointed representative at an online or offline event. Representation of a project may be further defined and clarified by the Strapi team.
|
||||
|
||||
### Enforcement
|
||||
|
||||
Instances of abusive, harassing, or otherwise unacceptable behavior may be reported by contacting the support team at [support@strapi.io](mailto:support@strapi.io). All complaints will be reviewed and investigated and will result in a response that is deemed necessary and appropriate to the circumstances. The project team is obligated to maintain confidentiality with regard to the reporter of an incident. Further details of specific enforcement policies may be posted separately.
|
||||
|
||||
Project maintainers and contributors who do not follow or enforce the Code of Conduct in good faith may face temporary or permanent repercussions as determined by other members of the project's leadership.
|
||||
@ -59,3 +59,4 @@
|
||||
* [Migrating from 3.0.0-alpha.8 to 3.0.0-alpha.9](migration/migration-guide-alpha-8-to-alpha-9.md)
|
||||
* [Migrating from 3.0.0-alpha.9 to 3.0.0-alpha.10](migration/migration-guide-alpha-9-to-alpha-10.md)
|
||||
* [Migrating from 3.0.0-alpha.10 to 3.0.0-alpha.11](migration/migration-guide-alpha-10-to-alpha-11.md)
|
||||
* [Migrating from 3.0.0-alpha.11 to 3.0.0-alpha.12](migration/migration-guide-alpha-11-to-alpha-12.md)
|
||||
|
||||
@ -16,7 +16,7 @@ module.exports = async (ctx, next) => {
|
||||
return await next();
|
||||
}
|
||||
|
||||
ctx.unauthorized(`You're not logged!`);
|
||||
ctx.unauthorized(`You're not logged in!`);
|
||||
};
|
||||
```
|
||||
|
||||
|
||||
@ -24,8 +24,9 @@ Create a development project
|
||||
To generate a new plugin **run the following commands:**
|
||||
1. In your project folder `cd myDevelopmentProject && strapi generate:plugin my-plugin`.
|
||||
2. Link the `strapi-helper-plugin` dependency in your project folder `cd pathToMyProject/myDevelopmentProject/plugins/my-plugin && npm link strapi-helper-plugin`.
|
||||
3. Start the server in the admin folder `cd pathToMyProject/myDevelopmentProject/admin && npm start` and go to the following url [http://localhost:4000/admin](http://localhost:4000/admin).
|
||||
4. In a new terminal window open at the root of your project launch your Strapi server `strapi start`.
|
||||
3. Link the `strapi-helper-plugin` dependency in the `analytics` plugin folder `cd pathToMyProject/myDevelopmentProject/plugins/analytics && npm link strapi-helper-plugin`.
|
||||
4. Start the server in the admin folder `cd pathToMyProject/myDevelopmentProject/admin && npm start` and go to the following url [http://localhost:4000/admin](http://localhost:4000/admin).
|
||||
5. In a new terminal window open at the root of your project launch your Strapi server `strapi start`.
|
||||
|
||||
|
||||
Your are now ready to develop your own plugin and live-test your updates!
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
{
|
||||
"private": true,
|
||||
"version": "3.0.0-alpha.12",
|
||||
"version": "3.0.0-alpha.12.1.3",
|
||||
"devDependencies": {
|
||||
"assert": "~1.3.0",
|
||||
"babel-eslint": "^6.1.2",
|
||||
|
||||
@ -1,3 +1,3 @@
|
||||
{
|
||||
"languages": ["en", "fr", "de", "pl", "tr", "zh"]
|
||||
"languages": ["en", "fr", "de", "pl", "tr", "zh", "zh-Hans"]
|
||||
}
|
||||
|
||||
162
packages/strapi-admin/admin/src/translations/zh-Hans.json
Normal file
162
packages/strapi-admin/admin/src/translations/zh-Hans.json
Normal file
@ -0,0 +1,162 @@
|
||||
{
|
||||
"app.components.Button.save": "保存",
|
||||
"app.components.Button.cancel": "取消",
|
||||
|
||||
"app.components.ComingSoonPage.comingSoon": "即将推出",
|
||||
"app.components.ComingSoonPage.featuresNotAvailable": "这个功能只在活跃开发中",
|
||||
|
||||
"app.components.DownloadInfo.download": "正在下载...",
|
||||
"app.components.DownloadInfo.text": "这可能需要几分钟,谢谢你的耐心。",
|
||||
|
||||
"app.components.HomePage.welcome": "欢迎回来",
|
||||
"app.components.HomePage.welcome.again": "欢迎 ",
|
||||
"app.components.HomePage.cta": "请确认",
|
||||
"app.components.HomePage.community": "在网络上找到社区",
|
||||
"app.components.HomePage.newsLetter": "订阅Strapi简讯",
|
||||
"app.components.HomePage.community.content": "与团队成员、贡献者和开发人员在不同的渠道进行讨论。",
|
||||
"app.components.HomePage.create": "创建第一个Content Type",
|
||||
"app.components.HomePage.welcomeBlock.content": "我们很高兴有你成为社区成员之一。我们一直在寻找反馈,所以可以随时给我们发送消息。 on\u0020",
|
||||
"app.components.HomePage.welcomeBlock.content.again": "我们希望你在项目上取得进展。请随意阅读关于Strapi的最新消息。我们将尽最大努力根据您的反馈改进产品。",
|
||||
"app.components.HomePage.welcomeBlock.content.issues": "issues.",
|
||||
"app.components.HomePage.welcomeBlock.content.raise": "\u0020or raise\u0020",
|
||||
"app.components.HomePage.createBlock.content.first": "The\u0020",
|
||||
"app.components.HomePage.createBlock.content.second": "\u0020插件将帮助您定义模型的数据结构。如果你是刚接触Strapi,我们强烈推荐你跟随我们。\u0020",
|
||||
"app.components.HomePage.createBlock.content.tutorial": "\u0020tutorial.",
|
||||
"app.components.HomePage.button.quickStart": "快速入门教程",
|
||||
"app.components.HomePage.button.blog": "在博客上看到更多",
|
||||
"app.components.HomePage.support": "支持我们",
|
||||
"app.components.HomePage.support.content": "通过购买T恤来支持我们,它将允许我们继续我们的项目工作,给你最好的体验!",
|
||||
"app.components.HomePage.support.link": "现在购买T恤",
|
||||
|
||||
"app.components.BlockLink.documentation": "阅读文档",
|
||||
"app.components.BlockLink.documentation.content": "发现基本概念,参考指南和教程。",
|
||||
"app.components.BlockLink.code": "代码示例",
|
||||
"app.components.BlockLink.code.content": "通过测试社区的真实项目来学习。",
|
||||
|
||||
|
||||
"app.components.InputFile.newFile": "增加新文件",
|
||||
"app.components.InputFileDetails.open": "在新选项卡中打开",
|
||||
"app.components.InputFileDetails.remove": "删除这个文件",
|
||||
"app.components.InputFileDetails.originalName": "原名称:",
|
||||
"app.components.InputFileDetails.size": "大小:",
|
||||
|
||||
"app.components.ImgPreview.hint": "将文件拖放到该区域或{browse}以供文件上载",
|
||||
"app.components.ImgPreview.hint.browse": "浏览",
|
||||
|
||||
"app.components.InstallPluginPage.helmet": "市场-插件",
|
||||
"app.components.InstallPluginPage.title": "市场-插件",
|
||||
"app.components.InstallPluginPage.description": "轻松地扩展你的应用程序。",
|
||||
"app.components.InstallPluginPage.plugin.support-us.description": "通过购买Strapi T恤支持我们。这将使我们能够继续致力于这个项目,并尝试给你最好的体验!",
|
||||
"app.components.InstallPluginPage.InputSearch.label": " ",
|
||||
"app.components.InstallPluginPage.InputSearch.placeholder": "搜索插件… (ex: authentication)",
|
||||
"app.components.InstallPluginPopup.downloads": "下载",
|
||||
"app.components.InstallPluginPopup.navLink.description": "描述",
|
||||
"app.components.InstallPluginPopup.navLink.screenshots": "截屏",
|
||||
"app.components.InstallPluginPopup.navLink.avis": "avis",
|
||||
"app.components.InstallPluginPopup.navLink.faq": "faq",
|
||||
"app.components.InstallPluginPopup.navLink.changelog": "更新日志",
|
||||
"app.components.InstallPluginPopup.noDescription": "没有描述",
|
||||
|
||||
"app.components.LeftMenuFooter.poweredBy": "技术支持",
|
||||
"app.components.LeftMenuLinkContainer.configuration": "配置",
|
||||
"app.components.LeftMenuLinkContainer.general": "一般",
|
||||
"app.components.LeftMenuLinkContainer.installNewPlugin": "市场",
|
||||
"app.components.LeftMenuLinkContainer.listPlugins": "插件",
|
||||
"app.components.LeftMenuLinkContainer.noPluginsInstalled": "还没有安装插件",
|
||||
"app.components.LeftMenuLinkContainer.plugins": "插件",
|
||||
|
||||
"app.components.ListPluginsPage.helmet.title": "插件列表",
|
||||
"app.components.ListPluginsPage.title": "插件",
|
||||
"app.components.ListPluginsPage.description": "项目中已安装的插件列表",
|
||||
"app.components.listPluginsPage.deletePlugin.error": "卸载插件时出错",
|
||||
"app.components.listPlugins.title.singular": "{number} 个插件已安装",
|
||||
"app.components.listPlugins.title.plural": "{number} 个插件已安装",
|
||||
"app.components.listPlugins.title.none": "还没有安装插件",
|
||||
"app.components.listPlugins.button": "增加新插件",
|
||||
|
||||
"app.components.NotFoundPage.description": "没有找到",
|
||||
"app.components.NotFoundPage.back": "返回主页",
|
||||
|
||||
"app.components.Official": "官方",
|
||||
|
||||
"app.components.PluginCard.compatible": "与你的应用程序兼容",
|
||||
"app.components.PluginCard.compatibleCommunity": "与社区兼容",
|
||||
"app.components.PluginCard.Button.label.download": "下载",
|
||||
"app.components.PluginCard.Button.label.install": "已下载",
|
||||
"app.components.PluginCard.Button.label.support": "支持我们",
|
||||
"app.components.PluginCard.price.free": "免费",
|
||||
"app.components.PluginCard.more-details": "更多细节",
|
||||
|
||||
"app.utils.placeholder.defaultMessage": "\u0020",
|
||||
"app.utils.SelectOption.defaultMessage": "\u0020",
|
||||
"app.utils.defaultMessage": "\u0020",
|
||||
|
||||
"components.AutoReloadBlocker.header": "这个插件需要重新加载特性。",
|
||||
"components.AutoReloadBlocker.description": "打开下面的文件并启用该特性。",
|
||||
|
||||
"components.ErrorBoundary.title": "哪里出问题了…",
|
||||
|
||||
"components.OverlayBlocker.title": "等待重新启动...",
|
||||
"components.OverlayBlocker.description": "这个功能成需要服务器重新启动。请等到服务器启动。",
|
||||
|
||||
"components.PageFooter.select": "每页条目",
|
||||
|
||||
"components.ProductionBlocker.header": "这个插件只能在开发中使用。",
|
||||
"components.ProductionBlocker.description": "为了安全起见,我们必须在其他环境中禁用这个插件。",
|
||||
|
||||
"components.popUpWarning.button.cancel": "取消",
|
||||
"components.popUpWarning.button.confirm": "确认",
|
||||
"components.popUpWarning.title": "请确认",
|
||||
"components.popUpWarning.message": "确实要删除这个吗?",
|
||||
|
||||
"components.Input.error.validation.email": "这不是电子邮件",
|
||||
"components.Input.error.validation.required": "这个值是必须的",
|
||||
"components.Input.error.validation.regex": "格式不正确",
|
||||
"components.Input.error.validation.max": "超过最大值",
|
||||
"components.Input.error.validation.min": "低于最小值",
|
||||
"components.Input.error.validation.maxLength": "超过最大长度",
|
||||
"components.Input.error.validation.minLength": "低于最小长度",
|
||||
"components.Input.error.contentTypeName.taken": "此名称已经存在",
|
||||
"components.Input.error.attribute.taken": "此字段名称已经存在",
|
||||
"components.Input.error.attribute.key.taken": "此值已经存在",
|
||||
"components.Input.error.attribute.sameKeyAndName": "不能相等",
|
||||
"components.Input.error.validation.minSupMax": "最小值超过最大值了",
|
||||
"components.Input.error.custom-error": "{errorMessage} ",
|
||||
|
||||
"components.ListRow.empty": "没有要显示的数据",
|
||||
|
||||
"components.Wysiwyg.collapse": "折叠",
|
||||
"components.Wysiwyg.selectOptions.title": "增加一个标题",
|
||||
"components.Wysiwyg.selectOptions.H1": "Title H1",
|
||||
"components.Wysiwyg.selectOptions.H2": "Title H2",
|
||||
"components.Wysiwyg.selectOptions.H3": "Title H3",
|
||||
"components.Wysiwyg.selectOptions.H4": "Title H4",
|
||||
"components.Wysiwyg.selectOptions.H5": "Title H5",
|
||||
"components.Wysiwyg.selectOptions.H6": "Title H6",
|
||||
"components.Wysiwyg.ToggleMode.markdown": "编辑",
|
||||
"components.Wysiwyg.ToggleMode.preview": "预览",
|
||||
"components.WysiwygBottomControls.charactersIndicators": "characters",
|
||||
"components.WysiwygBottomControls.uploadFiles": "拖放文件,从剪贴板粘贴或 {browse}.",
|
||||
"components.WysiwygBottomControls.uploadFiles.browse": "从文件夹选取",
|
||||
"components.WysiwygBottomControls.fullscreen": "最大化",
|
||||
|
||||
"HomePage.notification.newsLetter.success": "成功订阅简讯",
|
||||
|
||||
"notification.error": "发生了一个错误",
|
||||
"notification.error.layout": "无法获取布局",
|
||||
|
||||
"Users & Permissions": "用户 & 权限",
|
||||
"Content Manager": "内容管理",
|
||||
"Content Type Builder": "内容类型生成器",
|
||||
"Settings Manager": "管理设置",
|
||||
"Email": "邮件",
|
||||
"Password": "密码",
|
||||
"Username": "用户名",
|
||||
"Provider": "供应商",
|
||||
"ResetPasswordToken": "密码重置",
|
||||
"Role": "角色",
|
||||
"New entry": "新入口",
|
||||
"request.error.model.unknow": "这个模型已不存在",
|
||||
"Users": "用户",
|
||||
"Analytics": "分析"
|
||||
}
|
||||
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "strapi-admin",
|
||||
"version": "3.0.0-alpha.12",
|
||||
"version": "3.0.0-alpha.12.1.3",
|
||||
"description": "Strapi Admin",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
@ -31,8 +31,8 @@
|
||||
},
|
||||
"devDependencies": {
|
||||
"sanitize.css": "^4.1.0",
|
||||
"strapi-helper-plugin": "3.0.0-alpha.12",
|
||||
"strapi-utils": "3.0.0-alpha.12"
|
||||
"strapi-helper-plugin": "3.0.0-alpha.12.1.3",
|
||||
"strapi-utils": "3.0.0-alpha.12.1.3"
|
||||
},
|
||||
"author": {
|
||||
"name": "Strapi",
|
||||
|
||||
@ -43,9 +43,11 @@ module.exports = function(strapi) {
|
||||
* Initialize the hook
|
||||
*/
|
||||
|
||||
initialize: cb => {
|
||||
initialize: async cb => {
|
||||
const connections = _.pickBy(strapi.config.connections, { connector: 'strapi-bookshelf' });
|
||||
|
||||
const databaseUpdate = [];
|
||||
|
||||
_.forEach(connections, (connection, connectionName) => {
|
||||
// Apply defaults
|
||||
_.defaults(connection.settings, strapi.config.hook.settings.bookshelf);
|
||||
@ -237,6 +239,7 @@ module.exports = function(strapi) {
|
||||
const association = definition.associations
|
||||
.filter(association => association.nature.toLowerCase().indexOf('morph') !== -1)
|
||||
.filter(association => association.alias === path || association.via === path)[0];
|
||||
|
||||
if (association) {
|
||||
// Override on polymorphic path only.
|
||||
if (_.isString(path) && path === association.via) {
|
||||
@ -253,7 +256,11 @@ module.exports = function(strapi) {
|
||||
strapi.plugins[association.plugin].models[association.collection || association.model]:
|
||||
strapi.models[association.collection || association.model];
|
||||
|
||||
return `${association.alias}.${model.collectionName}`;
|
||||
return {
|
||||
[`${association.alias}.${model.collectionName}`]: function(query) {
|
||||
query.orderBy('created_at', 'desc');
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
@ -310,6 +317,233 @@ module.exports = function(strapi) {
|
||||
// Push attributes to be aware of model schema.
|
||||
target[model]._attributes = definition.attributes;
|
||||
|
||||
databaseUpdate.push(new Promise(async (resolve) => {
|
||||
// Equilize database tables
|
||||
const handler = async (table, attributes) => {
|
||||
const tableExist = await ORM.knex.schema.hasTable(table);
|
||||
|
||||
const getType = (attribute, name) => {
|
||||
let type;
|
||||
|
||||
if (!attribute.type) {
|
||||
// Add integer value if there is a relation
|
||||
const relation = definition.associations.find((association) => {
|
||||
return association.alias === name;
|
||||
});
|
||||
|
||||
switch (relation.nature) {
|
||||
case 'oneToOne':
|
||||
case 'manyToOne':
|
||||
type = definition.client === 'pg' ? 'integer' : 'int';
|
||||
break;
|
||||
default:
|
||||
return null;
|
||||
}
|
||||
} else {
|
||||
switch (attribute.type) {
|
||||
case 'text':
|
||||
case 'json':
|
||||
type = 'text';
|
||||
break;
|
||||
case 'string':
|
||||
case 'password':
|
||||
case 'email':
|
||||
type = 'varchar(255)';
|
||||
break;
|
||||
case 'integer':
|
||||
case 'biginteger':
|
||||
type = definition.client === 'pg' ? 'integer' : 'int';
|
||||
break;
|
||||
case 'float':
|
||||
case 'decimal':
|
||||
type = attribute.type;
|
||||
break;
|
||||
case 'date':
|
||||
case 'time':
|
||||
case 'datetime':
|
||||
case 'timestamp':
|
||||
type = definition.client === 'pg' ? 'timestamp with time zone' : 'timestamp DEFAULT CURRENT_TIMESTAMP';
|
||||
break;
|
||||
case 'timestampUpdate':
|
||||
type = definition.client === 'pg' ? 'timestamp with time zone' : 'timestamp DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP';
|
||||
break;
|
||||
case 'boolean':
|
||||
type = 'boolean';
|
||||
break;
|
||||
default:
|
||||
}
|
||||
}
|
||||
|
||||
return type;
|
||||
};
|
||||
|
||||
// Apply field type of attributes definition
|
||||
const generateColumns = (attrs, start) => {
|
||||
return Object.keys(attrs).reduce((acc, attr) => {
|
||||
const attribute = attributes[attr];
|
||||
|
||||
const type = getType(attribute, attr);
|
||||
|
||||
if (type) {
|
||||
acc.push(`${quote}${attr}${quote} ${type}`);
|
||||
}
|
||||
|
||||
return acc;
|
||||
}, start);
|
||||
};
|
||||
|
||||
if (!tableExist) {
|
||||
const columns = generateColumns(attributes, [`id ${definition.client === 'pg' ? 'SERIAL' : 'INT AUTO_INCREMENT'} NOT NULL PRIMARY KEY`]).join(',\n\r');
|
||||
|
||||
// Create table
|
||||
await ORM.knex.raw(`
|
||||
CREATE TABLE ${quote}${table}${quote} (
|
||||
${columns}
|
||||
)
|
||||
`);
|
||||
} else {
|
||||
const columns = Object.keys(attributes);
|
||||
|
||||
// Fetch existing column
|
||||
const columnsExist = await Promise.all(columns.map(attribute =>
|
||||
ORM.knex.schema.hasColumn(table, attribute)
|
||||
));
|
||||
|
||||
const columnsToAdd = {};
|
||||
|
||||
// Get columns to add
|
||||
columnsExist.forEach((columnExist, index) => {
|
||||
const attribute = attributes[columns[index]];
|
||||
|
||||
if (!columnExist) {
|
||||
columnsToAdd[columns[index]] = attribute;
|
||||
}
|
||||
});
|
||||
|
||||
// Generate and execute query to add missing column
|
||||
if (Object.keys(columnsToAdd).length > 0) {
|
||||
const columns = generateColumns(columnsToAdd, []);
|
||||
const queries = columns.reduce((acc, attribute) => {
|
||||
acc.push(`ALTER TABLE ${quote}${table}${quote} ADD ${attribute};`)
|
||||
return acc;
|
||||
}, []).join('\n\r');
|
||||
|
||||
await ORM.knex.raw(queries);
|
||||
}
|
||||
|
||||
// Execute query to update column type
|
||||
await Promise.all(columns.map(attribute =>
|
||||
new Promise(async (resolve) => {
|
||||
const type = getType(attributes[attribute], attribute);
|
||||
|
||||
if (type) {
|
||||
const changeType = definition.client === 'pg'
|
||||
? `ALTER COLUMN ${quote}${attribute}${quote} TYPE ${type} USING ${quote}${attribute}${quote}::${type}`
|
||||
: `CHANGE ${quote}${attribute}${quote} ${quote}${attribute}${quote} ${type} `;
|
||||
|
||||
const changeRequired = definition.client === 'pg'
|
||||
? `ALTER COLUMN ${quote}${attribute}${quote} ${attributes[attribute].required ? 'SET' : 'DROP'} NOT NULL`
|
||||
: `CHANGE ${quote}${attribute}${quote} ${quote}${attribute}${quote} ${type} ${attributes[attribute].required ? 'NOT' : ''} NULL`;
|
||||
|
||||
await ORM.knex.raw(`ALTER TABLE ${quote}${table}${quote} ${changeType}`);
|
||||
await ORM.knex.raw(`ALTER TABLE ${quote}${table}${quote} ${changeRequired}`);
|
||||
}
|
||||
|
||||
resolve();
|
||||
})
|
||||
));
|
||||
}
|
||||
};
|
||||
|
||||
const quote = definition.client === 'pg' ? '"' : '`';
|
||||
|
||||
// Add created_at and updated_at field if timestamp option is true
|
||||
if (loadedModel.hasTimestamps) {
|
||||
definition.attributes['created_at'] = {
|
||||
type: 'timestamp'
|
||||
};
|
||||
definition.attributes['updated_at'] = {
|
||||
type: 'timestampUpdate'
|
||||
};
|
||||
}
|
||||
|
||||
// Equilize tables
|
||||
await handler(loadedModel.tableName, definition.attributes);
|
||||
|
||||
// Equilize polymorphic releations
|
||||
const morphRelations = definition.associations.find((association) => {
|
||||
return association.nature.toLowerCase().includes('morphto');
|
||||
});
|
||||
|
||||
if (morphRelations) {
|
||||
const attributes = {
|
||||
[`${loadedModel.tableName}_id`]: {
|
||||
type: 'integer'
|
||||
},
|
||||
[`${morphRelations.alias}_id`]: {
|
||||
type: 'integer'
|
||||
},
|
||||
[`${morphRelations.alias}_type`]: {
|
||||
type: 'text'
|
||||
},
|
||||
[definition.attributes[morphRelations.alias].filter]: {
|
||||
type: 'text'
|
||||
}
|
||||
};
|
||||
|
||||
await handler(`${loadedModel.tableName}_morph`, attributes);
|
||||
}
|
||||
|
||||
// Equilize many to many releations
|
||||
const manyRelations = definition.associations.find((association) => {
|
||||
return association.nature === 'manyToMany';
|
||||
});
|
||||
|
||||
if (manyRelations && manyRelations.dominant) {
|
||||
const collection = manyRelations.plugin ?
|
||||
strapi.plugins[manyRelations.plugin].models[manyRelations.collection]:
|
||||
strapi.models[manyRelations.collection];
|
||||
|
||||
const attributes = {
|
||||
[`${pluralize.singular(manyRelations.collection)}_id`]: {
|
||||
type: 'integer'
|
||||
},
|
||||
[`${pluralize.singular(definition.globalId.toLowerCase())}_id`]: {
|
||||
type: 'integer'
|
||||
}
|
||||
};
|
||||
|
||||
const table = _.get(manyRelations, 'collectionName') ||
|
||||
_.map(
|
||||
_.sortBy(
|
||||
[
|
||||
collection.attributes[
|
||||
manyRelations.via
|
||||
],
|
||||
manyRelations
|
||||
],
|
||||
'collection'
|
||||
),
|
||||
table => {
|
||||
return _.snakeCase(
|
||||
pluralize.plural(table.collection) +
|
||||
' ' +
|
||||
pluralize.plural(table.via)
|
||||
);
|
||||
}
|
||||
).join('__');
|
||||
|
||||
await handler(table, attributes);
|
||||
}
|
||||
|
||||
// Remove from attributes (auto handled by bookshlef and not displayed on ctb)
|
||||
if (loadedModel.hasTimestamps) {
|
||||
delete definition.attributes['created_at'];
|
||||
delete definition.attributes['updated_at'];
|
||||
}
|
||||
|
||||
resolve();
|
||||
}));
|
||||
} catch (err) {
|
||||
strapi.log.error('Impossible to register the `' + model + '` model.');
|
||||
strapi.log.error(err);
|
||||
@ -605,6 +839,8 @@ module.exports = function(strapi) {
|
||||
});
|
||||
});
|
||||
|
||||
await Promise.all(databaseUpdate);
|
||||
|
||||
cb();
|
||||
},
|
||||
|
||||
|
||||
@ -4,6 +4,9 @@
|
||||
const execSync = require('child_process').execSync;
|
||||
const path = require('path');
|
||||
|
||||
// Public node modules
|
||||
const inquirer = require('inquirer');
|
||||
|
||||
// Logger.
|
||||
const logger = require('strapi-utils').logger;
|
||||
|
||||
@ -17,15 +20,45 @@ module.exports = (scope, success, error) => {
|
||||
|
||||
knex.raw('select 1+1 as result').then(() => {
|
||||
logger.info('The app has been connected to the database successfully');
|
||||
knex.destroy();
|
||||
execSync(`rm -r "${scope.tmpPath}"`);
|
||||
|
||||
logger.info('Copying the dashboard...');
|
||||
knex.raw(scope.client.database === 'postgres' ? "SELECT tablename FROM pg_tables WHERE schemaname='public'" : 'SELECT * FROM information_schema.tables').then((tables) => {
|
||||
knex.destroy();
|
||||
|
||||
success();
|
||||
})
|
||||
.catch(() => {
|
||||
logger.warn('Database connection has failed! Make sure your database is running.');
|
||||
error();
|
||||
const next = () => {
|
||||
execSync(`rm -r "${scope.tmpPath}"`);
|
||||
|
||||
logger.info('Copying the dashboard...');
|
||||
|
||||
success();
|
||||
};
|
||||
|
||||
if (tables.rows && tables.rows.length !== 0) {
|
||||
logger.warn('It seems that your database is not empty. Be aware that Strapi is going to automatically creates tables & columns, and might update columns which can corrupt data or cause data loss.');
|
||||
|
||||
inquirer.prompt([{
|
||||
type: 'confirm',
|
||||
prefix: '',
|
||||
name: 'confirm',
|
||||
message: `Are you sure you want to continue with the ${scope.database.settings.database} database:`,
|
||||
}])
|
||||
.then(({confirm}) => {
|
||||
if (confirm) {
|
||||
next();
|
||||
} else {
|
||||
error();
|
||||
}
|
||||
});
|
||||
} else {
|
||||
next();
|
||||
}
|
||||
});
|
||||
})
|
||||
.catch((err) => {
|
||||
if (err.sql) {
|
||||
logger.warn('Server connection has failed! Make sure your database server is running.');
|
||||
} else {
|
||||
logger.warn(`Database connection has failed! Make sure your "${scope.database.settings.database}" database exist.`);
|
||||
}
|
||||
error();
|
||||
});
|
||||
};
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "strapi-bookshelf",
|
||||
"version": "3.0.0-alpha.12",
|
||||
"version": "3.0.0-alpha.12.1.3",
|
||||
"description": "Bookshelf hook for the Strapi framework",
|
||||
"homepage": "http://strapi.io",
|
||||
"keywords": [
|
||||
@ -17,10 +17,11 @@
|
||||
"main": "./lib",
|
||||
"dependencies": {
|
||||
"bookshelf": "^0.12.1",
|
||||
"inquirer": "^5.2.0",
|
||||
"lodash": "^4.17.4",
|
||||
"pluralize": "^6.0.0",
|
||||
"strapi-knex": "3.0.0-alpha.12",
|
||||
"strapi-utils": "3.0.0-alpha.12"
|
||||
"strapi-knex": "3.0.0-alpha.12.1.3",
|
||||
"strapi-utils": "3.0.0-alpha.12.1.3"
|
||||
},
|
||||
"strapi": {
|
||||
"isHook": true,
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "strapi-ejs",
|
||||
"version": "3.0.0-alpha.12",
|
||||
"version": "3.0.0-alpha.12.1.3",
|
||||
"description": "EJS hook for the Strapi framework",
|
||||
"homepage": "http://strapi.io",
|
||||
"keywords": [
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "strapi-generate-admin",
|
||||
"version": "3.0.0-alpha.12",
|
||||
"version": "3.0.0-alpha.12.1.3",
|
||||
"description": "Generate the default admin panel for a Strapi application.",
|
||||
"homepage": "http://strapi.io",
|
||||
"keywords": [
|
||||
@ -15,7 +15,7 @@
|
||||
"dependencies": {
|
||||
"fs-extra": "^4.0.1",
|
||||
"lodash": "^4.17.4",
|
||||
"strapi-admin": "3.0.0-alpha.12"
|
||||
"strapi-admin": "3.0.0-alpha.12.1.3"
|
||||
},
|
||||
"author": {
|
||||
"email": "hi@strapi.io",
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "strapi-generate-api",
|
||||
"version": "3.0.0-alpha.12",
|
||||
"version": "3.0.0-alpha.12.1.3",
|
||||
"description": "Generate an API for a Strapi application.",
|
||||
"homepage": "http://strapi.io",
|
||||
"keywords": [
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "strapi-generate-controller",
|
||||
"version": "3.0.0-alpha.12",
|
||||
"version": "3.0.0-alpha.12.1.3",
|
||||
"description": "Generate a controller for a Strapi API.",
|
||||
"homepage": "http://strapi.io",
|
||||
"keywords": [
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "strapi-generate-model",
|
||||
"version": "3.0.0-alpha.12",
|
||||
"version": "3.0.0-alpha.12.1.3",
|
||||
"description": "Generate a model for a Strapi API.",
|
||||
"homepage": "http://strapi.io",
|
||||
"keywords": [
|
||||
|
||||
@ -84,21 +84,6 @@ module.exports = (scope, cb) => {
|
||||
connector: 'strapi-bookshelf',
|
||||
module: 'mysql'
|
||||
}
|
||||
},
|
||||
{
|
||||
name: 'Sqlite3',
|
||||
value: {
|
||||
database: 'sqlite3',
|
||||
connector: 'strapi-bookshelf',
|
||||
module: 'sqlite3'
|
||||
}
|
||||
},
|
||||
{
|
||||
name: 'Redis',
|
||||
value: {
|
||||
database: 'redis',
|
||||
connector: 'strapi-redis'
|
||||
}
|
||||
}
|
||||
];
|
||||
|
||||
@ -170,9 +155,7 @@ module.exports = (scope, cb) => {
|
||||
const ports = {
|
||||
mongo: 27017,
|
||||
postgres: 5432,
|
||||
mysql: 3306,
|
||||
sqlite3: 1433,
|
||||
redis: 6379
|
||||
mysql: 3306
|
||||
};
|
||||
|
||||
return ports[scope.client.database];
|
||||
@ -237,7 +220,7 @@ module.exports = (scope, cb) => {
|
||||
cmd += ` ${scope.client.module}`;
|
||||
}
|
||||
|
||||
if (scope.developerMode === true && scope.client.connector === 'strapi-bookshelf') {
|
||||
if (scope.client.connector === 'strapi-bookshelf') {
|
||||
cmd += ` strapi-knex@alpha`;
|
||||
|
||||
scope.additionalsDependencies = ['strapi-knex', 'knex'];
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "strapi-generate-new",
|
||||
"version": "3.0.0-alpha.12",
|
||||
"version": "3.0.0-alpha.12.1.3",
|
||||
"description": "Generate a new Strapi application.",
|
||||
"homepage": "http://strapi.io",
|
||||
"keywords": [
|
||||
@ -18,7 +18,7 @@
|
||||
"get-installed-path": "^3.0.1",
|
||||
"inquirer": "^4.0.2",
|
||||
"lodash": "^4.17.4",
|
||||
"strapi-utils": "3.0.0-alpha.12",
|
||||
"strapi-utils": "3.0.0-alpha.12.1.3",
|
||||
"uuid": "^3.1.0"
|
||||
},
|
||||
"scripts": {
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "strapi-generate-plugin",
|
||||
"version": "3.0.0-alpha.12",
|
||||
"version": "3.0.0-alpha.12.1.3",
|
||||
"description": "Generate an plugin for a Strapi application.",
|
||||
"homepage": "http://strapi.io",
|
||||
"keywords": [
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "strapi-generate-policy",
|
||||
"version": "3.0.0-alpha.12",
|
||||
"version": "3.0.0-alpha.12.1.3",
|
||||
"description": "Generate a policy for a Strapi API.",
|
||||
"homepage": "http://strapi.io",
|
||||
"keywords": [
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "strapi-generate-service",
|
||||
"version": "3.0.0-alpha.12",
|
||||
"version": "3.0.0-alpha.12.1.3",
|
||||
"description": "Generate a service for a Strapi API.",
|
||||
"homepage": "http://strapi.io",
|
||||
"keywords": [
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "strapi-generate",
|
||||
"version": "3.0.0-alpha.12",
|
||||
"version": "3.0.0-alpha.12.1.3",
|
||||
"description": "Master of ceremonies for the Strapi generators.",
|
||||
"homepage": "http://strapi.io",
|
||||
"keywords": [
|
||||
@ -17,7 +17,7 @@
|
||||
"fs-extra": "^4.0.0",
|
||||
"lodash": "^4.17.4",
|
||||
"reportback": "^2.0.1",
|
||||
"strapi-utils": "3.0.0-alpha.12"
|
||||
"strapi-utils": "3.0.0-alpha.12.1.3"
|
||||
},
|
||||
"author": {
|
||||
"name": "Strapi team",
|
||||
|
||||
@ -14,8 +14,10 @@ import cn from 'classnames';
|
||||
import styles from './styles.scss';
|
||||
|
||||
function InputTextArea(props) {
|
||||
const placeholder = isEmpty(props.placeholder) ? 'app.utils.placeholder.defaultMessage' : props.placeholder;
|
||||
|
||||
return (
|
||||
<FormattedMessage id={props.placeholder} defaultMessage={props.placeholder}>
|
||||
<FormattedMessage id={placeholder} defaultMessage={placeholder}>
|
||||
{(message) => (
|
||||
<textarea
|
||||
autoFocus={props.autoFocus}
|
||||
|
||||
@ -590,22 +590,40 @@ class Wysiwyg extends React.Component {
|
||||
'X-Forwarded-Host': 'strapi',
|
||||
};
|
||||
|
||||
const newContentState = this.createNewContentStateFromBlock(
|
||||
createNewBlock(`![Uploading ${files[0].name}]()`),
|
||||
);
|
||||
const newEditorState = EditorState.push(this.getEditorState(), newContentState);
|
||||
this.setState({ editorState: newEditorState });
|
||||
let newEditorState = this.getEditorState();
|
||||
|
||||
const nextBlocks = getNextBlocksList(newEditorState, this.getSelection().getStartKey());
|
||||
// Loop to update each block after the inserted li
|
||||
nextBlocks.map((block, index) => {
|
||||
// Update the current block
|
||||
const nextBlockText = index === 0 ? `![Uploading ${files[0].name}]()` : nextBlocks.get(index - 1).getText();
|
||||
const newBlock = createNewBlock(nextBlockText, 'unstyled', block.getKey());
|
||||
// Update the contentState
|
||||
const newContentState = this.createNewContentStateFromBlock(
|
||||
newBlock,
|
||||
newEditorState.getCurrentContent(),
|
||||
);
|
||||
newEditorState = EditorState.push(newEditorState, newContentState);
|
||||
});
|
||||
|
||||
const offset = `![Uploading ${files[0].name}]()`.length;
|
||||
const updatedSelection = updateSelection(this.getSelection(), nextBlocks, offset);
|
||||
this.setState({ editorState: EditorState.acceptSelection(newEditorState, updatedSelection) });
|
||||
|
||||
return request('/upload', { method: 'POST', headers, body: formData }, false, false)
|
||||
.then(response => {
|
||||
const lastBlock = this.getEditorState()
|
||||
const nextBlockKey = newEditorState
|
||||
.getCurrentContent()
|
||||
.getLastBlock();
|
||||
.getKeyAfter(newEditorState.getSelection().getStartKey());
|
||||
const content = ``;
|
||||
const newContentState = this.createNewContentStateFromBlock(
|
||||
createNewBlock(``, 'unstyled', lastBlock.getKey()),
|
||||
createNewBlock(content, 'unstyled', nextBlockKey),
|
||||
);
|
||||
const newEditorState = EditorState.push(this.getEditorState(), newContentState);
|
||||
this.setState({ editorState: EditorState.moveFocusToEnd(newEditorState) });
|
||||
|
||||
newEditorState = EditorState.push(newEditorState, newContentState);
|
||||
const updatedSelection = updateSelection(this.getSelection(), nextBlocks, 2);
|
||||
|
||||
this.setState({ editorState: EditorState.acceptSelection(newEditorState, updatedSelection) });
|
||||
this.sendData(newEditorState);
|
||||
})
|
||||
.catch(() => {
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "strapi-helper-plugin",
|
||||
"version": "3.0.0-alpha.12",
|
||||
"version": "3.0.0-alpha.12.1.3",
|
||||
"description": "Helper for Strapi plugins development",
|
||||
"engines": {
|
||||
"node": ">= 9.0.0",
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "strapi-knex",
|
||||
"version": "3.0.0-alpha.12",
|
||||
"version": "3.0.0-alpha.12.1.3",
|
||||
"description": "Knex hook for the Strapi framework",
|
||||
"homepage": "http://strapi.io",
|
||||
"keywords": [
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "strapi-middleware-views",
|
||||
"version": "3.0.0-alpha.12",
|
||||
"version": "3.0.0-alpha.12.1.3",
|
||||
"description": "Views hook to enable server-side rendering for the Strapi framework",
|
||||
"homepage": "http://strapi.io",
|
||||
"keywords": [
|
||||
|
||||
@ -29,8 +29,6 @@ module.exports = (scope, success, error) => {
|
||||
|
||||
connectOptions.ssl = ssl ? true : false;
|
||||
|
||||
console.log(connectOptions);
|
||||
|
||||
Mongoose.connect(`mongodb://${scope.database.settings.host}:${scope.database.settings.port}/${scope.database.settings.database}`, connectOptions, function (err) {
|
||||
if (err) {
|
||||
logger.warn('Database connection has failed! Make sure your database is running.');
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "strapi-mongoose",
|
||||
"version": "3.0.0-alpha.12",
|
||||
"version": "3.0.0-alpha.12.1.3",
|
||||
"description": "Mongoose hook for the Strapi framework",
|
||||
"homepage": "http://strapi.io",
|
||||
"keywords": [
|
||||
@ -19,7 +19,7 @@
|
||||
"mongoose": "^5.0.16",
|
||||
"mongoose-float": "^1.0.2",
|
||||
"pluralize": "^6.0.0",
|
||||
"strapi-utils": "3.0.0-alpha.12"
|
||||
"strapi-utils": "3.0.0-alpha.12.1.3"
|
||||
},
|
||||
"strapi": {
|
||||
"isHook": true
|
||||
|
||||
@ -32,7 +32,7 @@ function EditRelations(props) {
|
||||
{map(filterRelationsUpload(props.schema.relations), (relation, key) => {
|
||||
if (relation.nature.toLowerCase().includes('morph') && relation[key]) return '';
|
||||
|
||||
const Select = ['oneWay', 'oneToOne', 'manyToOne', 'oneToManyMorph', 'oneToOneMorph'].includes(relation.nature) && relation.dominant ? SelectOne : SelectMany;
|
||||
const Select = ['oneWay', 'oneToOne', 'manyToOne', 'oneToManyMorph', 'oneToOneMorph'].includes(relation.nature) ? SelectOne : SelectMany;
|
||||
|
||||
return (
|
||||
<Select
|
||||
|
||||
@ -0,0 +1,55 @@
|
||||
{
|
||||
"plugin.description.short": "快速查看、编辑和删除数据库中的数据。",
|
||||
"plugin.description.long": "快速查看、编辑和删除数据库中的数据。",
|
||||
"containers.Home.pluginHeaderTitle": "内容管理器",
|
||||
"containers.Home.introduction": "要编辑您的条目,请转到左边菜单中的特定链接。这个插件没有合适的方法来编辑设置,它仍然在积极的开发中。",
|
||||
"containers.Home.pluginHeaderDescription": "通过一个强大而漂亮的界面管理你的条目。",
|
||||
"containers.Edit.submit": "保存",
|
||||
"containers.Edit.editing": "编辑...",
|
||||
"containers.Edit.delete": "删除",
|
||||
"containers.Edit.reset": "重置",
|
||||
"containers.Edit.returnList": "返回列表",
|
||||
"containers.List.addAnEntry": "增加新的 {entity}",
|
||||
"containers.List.pluginHeaderDescription": "找到 {label} 条目",
|
||||
"containers.List.pluginHeaderDescription.singular": "找到 {label} 条目",
|
||||
"components.LimitSelect.itemsPerPage": "每页显示数目",
|
||||
"containers.List.errorFetchRecords": "错误",
|
||||
|
||||
"EditRelations.title": "关系数据",
|
||||
|
||||
"emptyAttributes.title": "还没有字段",
|
||||
"emptyAttributes.description": "为你的内容类型添加第一个字段",
|
||||
"emptyAttributes.button": "转到内容类型生成器",
|
||||
|
||||
"error.schema.generation": "Schema生成过程中发生错误。",
|
||||
"error.records.count": "获取记录数count时发生错误。",
|
||||
"error.records.fetch": "获取记录时发生错误。",
|
||||
"error.record.fetch": "获取记录时发生错误。",
|
||||
"error.record.create": "创建记录时发生错误",
|
||||
"error.record.update": "更新记录时发生错误",
|
||||
"error.record.delete": "删除记录时发生错误",
|
||||
"error.model.fetch": "获取models配置时发生错误",
|
||||
"error.validation.required": "必填项",
|
||||
"error.validation.regex": "格式错误",
|
||||
"error.validation.max": "超过最大值",
|
||||
"error.validation.min": "小于最小值",
|
||||
"error.validation.maxLength": "长度太长",
|
||||
"error.validation.minLength": "长度太短",
|
||||
"error.contentTypeName.taken": "该名称已被使用",
|
||||
"error.attribute.taken": "该名称已被使用",
|
||||
"error.attribute.key.taken": "该值已存在",
|
||||
"error.attribute.sameKeyAndName": "不能相等",
|
||||
"error.validation.minSupMax": "最小值大于最大值。",
|
||||
|
||||
"notification.error.relationship.fetch": "获取关联数据时发生错误",
|
||||
|
||||
"success.record.delete": "删除",
|
||||
"success.record.save": "保存",
|
||||
|
||||
"pageNotFound": "页面未找到",
|
||||
|
||||
"popUpWarning.button.cancel": "取消",
|
||||
"popUpWarning.button.confirm": "确认",
|
||||
"popUpWarning.title": "请确认",
|
||||
"popUpWarning.bodyMessage.contentType.delete": "确实要删除此条目吗?"
|
||||
}
|
||||
@ -78,7 +78,7 @@ module.exports = {
|
||||
return acc;
|
||||
}, {});
|
||||
|
||||
const entry = await this
|
||||
const request = await this
|
||||
.forge(values)
|
||||
.save()
|
||||
.catch((err) => {
|
||||
@ -90,11 +90,18 @@ module.exports = {
|
||||
throw err;
|
||||
});
|
||||
|
||||
const entry = request.toJSON ? request.toJSON() : request;
|
||||
|
||||
const relations = this.associations.reduce((acc, association) => {
|
||||
acc[association.alias] = params.values[association.alias];
|
||||
return acc;
|
||||
}, {});
|
||||
|
||||
return module.exports.update.call(this, {
|
||||
[this.primaryKey]: entry[this.primaryKey],
|
||||
values: _.assign({
|
||||
id: entry[this.primaryKey]
|
||||
}, params.values, entry)
|
||||
}, relations)
|
||||
});
|
||||
},
|
||||
|
||||
@ -167,9 +174,7 @@ module.exports = {
|
||||
case 'oneToMany':
|
||||
case 'manyToOne':
|
||||
case 'manyToMany':
|
||||
if (association.nature === 'manyToMany' && details.dominant === true) {
|
||||
acc[current] = params.values[current];
|
||||
} else if (response[current] && _.isArray(response[current]) && current !== 'id') {
|
||||
if (response[current] && _.isArray(response[current]) && current !== 'id') {
|
||||
// Records to add in the relation.
|
||||
const toAdd = _.differenceWith(params.values[current], response[current], (a, b) =>
|
||||
a[this.primaryKey].toString() === b[this.primaryKey].toString()
|
||||
@ -213,13 +218,35 @@ module.exports = {
|
||||
strapi.plugins[obj.source].models[obj.ref]:
|
||||
strapi.models[obj.ref];
|
||||
|
||||
virtualFields.push(module.exports.addRelationMorph.call(this, {
|
||||
id: response[this.primaryKey],
|
||||
alias: association.alias,
|
||||
ref: model.collectionName,
|
||||
refId: obj.refId,
|
||||
field: obj.field
|
||||
}));
|
||||
// Remove existing relationship because only one file
|
||||
// can be related to this field.
|
||||
if (association.nature === 'manyMorphToOne') {
|
||||
virtualFields.push(
|
||||
module.exports.removeRelationMorph.call(this, {
|
||||
alias: association.alias,
|
||||
ref: model.collectionName,
|
||||
refId: obj.refId,
|
||||
field: obj.field
|
||||
})
|
||||
.then(() =>
|
||||
module.exports.addRelationMorph.call(this, {
|
||||
id: response[this.primaryKey],
|
||||
alias: association.alias,
|
||||
ref: model.collectionName,
|
||||
refId: obj.refId,
|
||||
field: obj.field
|
||||
})
|
||||
)
|
||||
);
|
||||
} else {
|
||||
virtualFields.push(module.exports.addRelationMorph.call(this, {
|
||||
id: response[this.primaryKey],
|
||||
alias: association.alias,
|
||||
ref: model.collectionName,
|
||||
refId: obj.refId,
|
||||
field: obj.field
|
||||
}));
|
||||
}
|
||||
});
|
||||
break;
|
||||
case 'oneToManyMorph':
|
||||
@ -236,7 +263,7 @@ module.exports = {
|
||||
}
|
||||
|
||||
if (association.type === 'model' || (association.type === 'collection' && _.isObject(array))) {
|
||||
return _.isEmpty(array) ? [] : transformToArrayID([array]);
|
||||
return _.isEmpty(_.toString(array)) ? [] : transformToArrayID([array]);
|
||||
}
|
||||
|
||||
return [];
|
||||
@ -382,12 +409,12 @@ module.exports = {
|
||||
|
||||
removeRelationMorph: async function (params) {
|
||||
return await this.morph.forge()
|
||||
.where({
|
||||
.where(_.omitBy({
|
||||
[`${this.collectionName}_id`]: params.id,
|
||||
[`${params.alias}_id`]: params.refId,
|
||||
[`${params.alias}_type`]: params.ref,
|
||||
field: params.field
|
||||
})
|
||||
}, _.isEmpty))
|
||||
.destroy();
|
||||
}
|
||||
};
|
||||
|
||||
@ -46,11 +46,19 @@ module.exports = {
|
||||
|
||||
const entry = request.toJSON ? request.toJSON() : request;
|
||||
|
||||
const relations = this.associations.reduce((acc, association) => {
|
||||
if (params.values[association.alias]) {
|
||||
acc[association.alias] = params.values[association.alias];
|
||||
}
|
||||
|
||||
return acc;
|
||||
}, {});
|
||||
|
||||
return module.exports.update.call(this, {
|
||||
[this.primaryKey]: entry[this.primaryKey],
|
||||
values: _.assign({
|
||||
id: entry[this.primaryKey]
|
||||
}, params.values, entry)
|
||||
}, relations)
|
||||
});
|
||||
},
|
||||
|
||||
@ -169,7 +177,7 @@ module.exports = {
|
||||
|
||||
virtualFields.push(strapi.query(details.model || details.collection, details.plugin).addRelation({
|
||||
id: value[this.primaryKey] || value.id || value._id,
|
||||
values: value,
|
||||
values: _.pick(value, [this.primaryKey, details.via]),
|
||||
foreignKey: current
|
||||
}));
|
||||
});
|
||||
@ -183,7 +191,7 @@ module.exports = {
|
||||
|
||||
virtualFields.push(strapi.query(details.model || details.collection, details.plugin).removeRelation({
|
||||
id: value[this.primaryKey] || value.id || value._id,
|
||||
values: value,
|
||||
values: _.pick(value, [this.primaryKey, details.via]),
|
||||
foreignKey: current
|
||||
}));
|
||||
});
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "strapi-plugin-content-manager",
|
||||
"version": "3.0.0-alpha.12",
|
||||
"version": "3.0.0-alpha.12.1.3",
|
||||
"description": "A powerful UI to easily manage your data.",
|
||||
"strapi": {
|
||||
"name": "Content Manager",
|
||||
@ -23,7 +23,7 @@
|
||||
},
|
||||
"devDependencies": {
|
||||
"react-select": "^1.0.0-rc.5",
|
||||
"strapi-helper-plugin": "3.0.0-alpha.12"
|
||||
"strapi-helper-plugin": "3.0.0-alpha.12.1.3"
|
||||
},
|
||||
"author": {
|
||||
"name": "Strapi team",
|
||||
@ -46,4 +46,4 @@
|
||||
"npm": ">= 5.0.0"
|
||||
},
|
||||
"license": "MIT"
|
||||
}
|
||||
}
|
||||
@ -50,6 +50,7 @@ import styles from './styles.scss';
|
||||
|
||||
// Array of attributes that the ctb can handle at the moment
|
||||
const availableAttributes = Object.keys(forms.attribute);
|
||||
availableAttributes.push('integer', 'decimal', 'float');
|
||||
|
||||
/* eslint-disable jsx-a11y/no-static-element-interactions */
|
||||
/* eslint-disable react/jsx-wrap-multilines */
|
||||
@ -90,25 +91,6 @@ export class ModelPage extends React.Component { // eslint-disable-line react/pr
|
||||
}
|
||||
}
|
||||
|
||||
// componentWillUpdate(nextProps) {
|
||||
// if (!isEmpty(nextProps.menu)) {
|
||||
// const allowedPaths = nextProps.menu.reduce((acc, current) => {
|
||||
// const models = current.items.reduce((acc, current) => {
|
||||
// acc.push(current.name);
|
||||
//
|
||||
// return acc;
|
||||
// }, []);
|
||||
// return acc.concat(models);
|
||||
// }, []);
|
||||
//
|
||||
// const shouldRedirect = allowedPaths.filter(el => el === this.props.match.params.modelName.split('&')[0]).length === 0;
|
||||
//
|
||||
// if (shouldRedirect) {
|
||||
// this.props.history.push('/404');
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
|
||||
componentDidUpdate(prevProps) {
|
||||
if (prevProps.match.params.modelName !== this.props.match.params.modelName) {
|
||||
this.props.resetShowButtonsProps();
|
||||
|
||||
@ -0,0 +1,174 @@
|
||||
{
|
||||
"plugin.description.short": "给你的API的数据结构建模",
|
||||
"plugin.description.long":
|
||||
"给你的API的数据结构建模. 快速的创造新的字段(fields)和关系(relations)。将会自动在项目中创建和更新文件。",
|
||||
"attribute.string": "String",
|
||||
"attribute.text": "Text",
|
||||
"attribute.boolean": "Boolean",
|
||||
"attribute.float": "Float",
|
||||
"attribute.integer": "integer",
|
||||
"attribute.decimal": "Decimal",
|
||||
"attribute.date": "Date",
|
||||
"attribute.json": "JSON",
|
||||
"attribute.media": "Media",
|
||||
"attribute.email": "Email",
|
||||
"attribute.password": "Password",
|
||||
"attribute.relation": "Relation",
|
||||
"attribute.enumeration": "Enumeration",
|
||||
"attribute.WYSIWYG": "Text (WYSIWYG)",
|
||||
|
||||
"contentType.temporaryDisplay": "(未保存)",
|
||||
"from": "from",
|
||||
"home.contentTypeBuilder.name": "Content Types",
|
||||
"home.contentTypeBuilder.description": "创建和更新自己Content Types.",
|
||||
"home.emptyContentType.title": "没有可用的Content Types",
|
||||
"home.emptyContentType.description":
|
||||
"创建第一个Content Type,以便能够从API中检索数据。",
|
||||
|
||||
"home.emptyAttributes.title": "还没有字段",
|
||||
"home.emptyAttributes.description": "为你的新Content Type添加第一个字段",
|
||||
|
||||
"button.contentType.create": "创建Content Type",
|
||||
"button.contentType.add": "增加Content Type",
|
||||
"button.attributes.add": "增加New字段",
|
||||
|
||||
"error.validation.required": "必填项",
|
||||
"error.validation.regex": "格式错误",
|
||||
"error.validation.max": "超过最大值",
|
||||
"error.validation.min": "低于最小值",
|
||||
"error.validation.maxLength": "超过最大长度",
|
||||
"error.validation.minLength": "小于最小长度",
|
||||
"error.contentTypeName.taken": "名称已存在",
|
||||
"error.attribute.taken": "字段名称已存在",
|
||||
"error.attribute.key.taken": "该值已存在",
|
||||
"error.attribute.sameKeyAndName": "不能相等",
|
||||
"error.validation.minSupMax": "最小值大于最大值。",
|
||||
|
||||
"form.attribute.item.textarea.name": "Name",
|
||||
"form.attribute.item.number.name": "Name",
|
||||
"form.attribute.item.date.name": "Name",
|
||||
"form.attribute.item.media.name": "Name",
|
||||
"form.attribute.item.media.multiple": "允许多个文件",
|
||||
"form.attribute.item.json.name": "Name",
|
||||
"form.attribute.item.boolean.name": "Name",
|
||||
"form.attribute.item.string.name": "Name",
|
||||
"form.attribute.item.appearance.name": "Appearance",
|
||||
"form.attribute.item.appearance.label": "Display as a WYSIWYG",
|
||||
"form.attribute.item.appearance.description":
|
||||
"否则,该值将通过基本文本字段进行编辑。",
|
||||
"form.attribute.item.settings.name": "设置",
|
||||
"form.attribute.item.requiredField": "必须的",
|
||||
"form.attribute.item.uniqueField": "唯一的",
|
||||
"form.attribute.item.minimum": "最小值",
|
||||
"form.attribute.item.minimumLength": "最小长度",
|
||||
"form.attribute.item.maximumLength": "最大长度",
|
||||
"form.attribute.item.maximum": "最大值",
|
||||
"form.attribute.item.requiredField.description":
|
||||
"如果此字段为空,则无法创建条目。",
|
||||
"form.attribute.item.uniqueField.description":
|
||||
"如果存在具有相同内容的现有条目,则无法创建条目。",
|
||||
"form.attribute.item.defineRelation.fieldName": "Field name",
|
||||
"form.attribute.item.customColumnName": "Custom column names",
|
||||
"form.attribute.item.customColumnName.description":"修改数据库列名,使得API返回更容易理解。",
|
||||
"form.attribute.item.number.type": "Number format",
|
||||
"form.attribute.item.number.type.integer": "integer (ex: 10)",
|
||||
"form.attribute.item.number.type.float": "float (ex: 3.33333333)",
|
||||
"form.attribute.item.number.type.decimal": "decimal (ex: 2.22)",
|
||||
"form.attribute.settings.default": "默认值",
|
||||
"form.attribute.settings.default.checkboxLabel": "Set to true",
|
||||
|
||||
"form.button.cancel": "取消",
|
||||
"form.button.continue": "继续",
|
||||
"form.button.save": "保存",
|
||||
|
||||
"form.contentType.item.connections": "连接",
|
||||
"form.contentType.item.name": "名称",
|
||||
"form.contentType.item.name.description": "Content Type names should be singular: {link}",
|
||||
"form.contentType.item.name.link.description": "查看我们的文档",
|
||||
"form.contentType.item.description": "描述",
|
||||
"form.contentType.item.description.placeholder": "在这里写下你的描述...",
|
||||
"form.contentType.item.collectionName": "Collection Name",
|
||||
"form.contentType.item.collectionName.inputDescription":
|
||||
"当你的Content Type和你的数据库表名不一样的时候",
|
||||
|
||||
"menu.section.contentTypeBuilder.name.plural": "Content Types",
|
||||
"menu.section.contentTypeBuilder.name.singular": "Content Type",
|
||||
"menu.section.documentation.name": "Documentation",
|
||||
"menu.section.documentation.guide": "阅读更多关于我们的Content Types",
|
||||
"menu.section.documentation.guideLink": "guide.",
|
||||
"menu.section.documentation.tutorial": "看看我们的",
|
||||
"menu.section.documentation.tutorialLink": "教程视频。",
|
||||
|
||||
"modelPage.contentHeader.emptyDescription.description": "该Content Type没有任何描述",
|
||||
"modelPage.contentType.list.title.plural": "fields",
|
||||
"modelPage.contentType.list.title.singular": "field",
|
||||
"modelPage.contentType.list.title.including": "including",
|
||||
"modelPage.contentType.list.relationShipTitle.plural": "relationships",
|
||||
"modelPage.contentType.list.relationShipTitle.singular": "relationship",
|
||||
"modelPage.attribute.relationWith": "Relation with",
|
||||
|
||||
"noTableWarning.description": "不要忘了在数据库里创建表 `{modelName}`",
|
||||
"noTableWarning.infos": "更多信息",
|
||||
|
||||
"notification.error.message": "发生错误",
|
||||
"notification.info.contentType.creating.notSaved":
|
||||
"在创建新Content Type之前,请保存当前Content Type",
|
||||
"notification.info.optimized": "这个插件是用本地存储优化的",
|
||||
"notification.success.message.contentType.edit": "你的Content Type已更新",
|
||||
"notification.success.message.contentType.create": "你的Content Type已创建",
|
||||
"notification.success.contentTypeDeleted": "这个Content Type已被删除",
|
||||
"notification.info.enumeration": "这个字段暂时不可编辑...😮",
|
||||
|
||||
"popUpForm.attributes.string.description": "标题、名称、段落、名称列表",
|
||||
"popUpForm.attributes.text.description": "描述、文本段落、文章",
|
||||
"popUpForm.attributes.boolean.description": "Yes or no, 1 or 0, true or false",
|
||||
"popUpForm.attributes.number.description": "所有数字",
|
||||
"popUpForm.attributes.date.description": "活动日期、开放时间",
|
||||
"popUpForm.attributes.json.description": "JSON格式的数据",
|
||||
"popUpForm.attributes.media.description": "图像,视频,PDF文件和其他文件",
|
||||
"popUpForm.attributes.relation.description": "引用其它 Content Type",
|
||||
"popUpForm.attributes.email.description": "用户email...",
|
||||
"popUpForm.attributes.password.description": "用户密码...",
|
||||
|
||||
"popUpForm.attributes.string.name": "String",
|
||||
"popUpForm.attributes.text.name": "Text",
|
||||
"popUpForm.attributes.boolean.name": "Boolean",
|
||||
"popUpForm.attributes.date.name": "Date",
|
||||
"popUpForm.attributes.json.name": "JSON",
|
||||
"popUpForm.attributes.media.name": "Media",
|
||||
"popUpForm.attributes.number.name": "Number",
|
||||
"popUpForm.attributes.relation.name": "Relation",
|
||||
"popUpForm.attributes.email.name": "Email",
|
||||
"popUpForm.attributes.password.name": "Password",
|
||||
"popUpForm.create": "增加新的",
|
||||
"popUpForm.edit": "编辑",
|
||||
"popUpForm.field": "字段",
|
||||
"popUpForm.create.contentType.header.title": "增加新的 Content Type",
|
||||
"popUpForm.choose.attributes.header.title": "增加新字段",
|
||||
"popUpForm.edit.contentType.header.title": "编辑 Content Type",
|
||||
|
||||
"popUpForm.navContainer.relation": "定义关联关系",
|
||||
"popUpForm.navContainer.base": "基础设置",
|
||||
"popUpForm.navContainer.advanced": "高级设置",
|
||||
|
||||
"popUpRelation.title": "关联",
|
||||
|
||||
"popUpWarning.button.cancel": "取消",
|
||||
"popUpWarning.button.confirm": "确认",
|
||||
"popUpWarning.title": "请确认",
|
||||
"popUpWarning.bodyMessage.contentType.delete":
|
||||
"确实要删除此 Content Type 吗?",
|
||||
"popUpWarning.bodyMessage.attribute.delete": "确实要删除此字段吗?",
|
||||
|
||||
"table.contentType.title.plural": "Content Types 是可用的",
|
||||
"table.contentType.title.singular": "Content Type 是可用的",
|
||||
"table.contentType.head.name": "名称",
|
||||
"table.contentType.head.description": "描述",
|
||||
"table.contentType.head.fields": "字段",
|
||||
|
||||
"relation.oneToOne": "has one",
|
||||
"relation.oneToMany": "belongs to many",
|
||||
"relation.manyToOne": "has many",
|
||||
"relation.manyToMany": "has and belongs to many",
|
||||
"relation.attributeName.placeholder": "Ex: author, category, tag"
|
||||
}
|
||||
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "strapi-plugin-content-type-builder",
|
||||
"version": "3.0.0-alpha.12",
|
||||
"version": "3.0.0-alpha.12.1.3",
|
||||
"description": "Strapi plugin to create content type (API).",
|
||||
"strapi": {
|
||||
"name": "Content Type Builder",
|
||||
@ -23,11 +23,11 @@
|
||||
},
|
||||
"dependencies": {
|
||||
"pluralize": "^7.0.0",
|
||||
"strapi-generate": "3.0.0-alpha.12",
|
||||
"strapi-generate-api": "3.0.0-alpha.12"
|
||||
"strapi-generate": "3.0.0-alpha.12.1.3",
|
||||
"strapi-generate-api": "3.0.0-alpha.12.1.3"
|
||||
},
|
||||
"devDependencies": {
|
||||
"strapi-helper-plugin": "3.0.0-alpha.12"
|
||||
"strapi-helper-plugin": "3.0.0-alpha.12.1.3"
|
||||
},
|
||||
"author": {
|
||||
"name": "Strapi team",
|
||||
@ -50,4 +50,4 @@
|
||||
"npm": ">= 5.0.0"
|
||||
},
|
||||
"license": "MIT"
|
||||
}
|
||||
}
|
||||
@ -214,7 +214,10 @@ module.exports = {
|
||||
|
||||
attr.via = relation.key;
|
||||
attr.dominant = relation.dominant;
|
||||
attr.plugin = relation.pluginValue;
|
||||
|
||||
if (_.trim(relation.pluginValue)) {
|
||||
attr.plugin = _.trim(relation.pluginValue);
|
||||
}
|
||||
|
||||
attrs[attribute.name] = attr;
|
||||
}
|
||||
@ -355,15 +358,23 @@ module.exports = {
|
||||
attr.model = model.toLowerCase();
|
||||
break;
|
||||
case 'manyToOne':
|
||||
attr.collection = model.toLowerCase();
|
||||
case 'manyToMany':
|
||||
attr.collection = model.toLowerCase();
|
||||
|
||||
if (!params.dominant) {
|
||||
attr.dominant = true;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
}
|
||||
|
||||
attr.via = name;
|
||||
attr.columnName = params.targetColumnName;
|
||||
attr.plugin = source;
|
||||
|
||||
if (_.trim(source)) {
|
||||
attr.plugin = _.trim(source);
|
||||
}
|
||||
|
||||
modelJSON.attributes[params.key] = attr;
|
||||
|
||||
|
||||
@ -0,0 +1,4 @@
|
||||
{
|
||||
"plugin.description.short": "发送电子邮件。",
|
||||
"plugin.description.long": "发送电子邮件。"
|
||||
}
|
||||
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "strapi-plugin-email",
|
||||
"version": "3.0.0-alpha.12",
|
||||
"version": "3.0.0-alpha.12.1.3",
|
||||
"description": "This is the description of the plugin.",
|
||||
"strapi": {
|
||||
"name": "Email",
|
||||
@ -25,7 +25,7 @@
|
||||
"sendmail": "^1.2.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"strapi-helper-plugin": "3.0.0-alpha.12"
|
||||
"strapi-helper-plugin": "3.0.0-alpha.12.1.3"
|
||||
},
|
||||
"author": {
|
||||
"name": "Strapi team",
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "strapi-plugin-graphql",
|
||||
"version": "3.0.0-alpha.12",
|
||||
"version": "3.0.0-alpha.12.1.3",
|
||||
"description": "This is the description of the plugin.",
|
||||
"strapi": {
|
||||
"name": "graphql",
|
||||
@ -27,7 +27,7 @@
|
||||
"graphql-tools": "^2.23.1",
|
||||
"graphql-type-json": "^0.2.0",
|
||||
"pluralize": "^7.0.0",
|
||||
"strapi-utils": "3.0.0-alpha.12"
|
||||
"strapi-utils": "3.0.0-alpha.12.1.3"
|
||||
},
|
||||
"author": {
|
||||
"name": "A Strapi developer",
|
||||
|
||||
@ -29,12 +29,13 @@
|
||||
"form.database.item.port": "Port",
|
||||
"form.database.item.username": "Benutzername",
|
||||
"form.database.item.password": "Passwort",
|
||||
"form.database.item.database": "Datenbanken",
|
||||
"form.database.item.database": "Datenbank",
|
||||
"form.database.item.ssl": "SSL",
|
||||
"form.database.item.authenticationDatabase": "Authentifizierungsdatenbank",
|
||||
"form.database.item.default": "Als Standard festgelegt",
|
||||
"form.database.item.provider.mongo": "Mongo",
|
||||
"form.database.item.provider.postgres": "PostgreSQL",
|
||||
"form.database.item.provider.mysql": "MySQL",
|
||||
"form.database.item.provider.sqlite3": "SQlite3",
|
||||
"form.database.item.provider.redis": "Redis",
|
||||
|
||||
"form.application.name": "Anwendung",
|
||||
|
||||
@ -29,12 +29,13 @@
|
||||
"form.database.item.port": "Port",
|
||||
"form.database.item.username": "Username",
|
||||
"form.database.item.password": "Password",
|
||||
"form.database.item.database": "Databases",
|
||||
"form.database.item.database": "Database",
|
||||
"form.database.item.ssl": "SSL",
|
||||
"form.database.item.authenticationDatabase": "Authentication Database",
|
||||
"form.database.item.default": "Set as default connection",
|
||||
"form.database.item.provider.mongo": "Mongo",
|
||||
"form.database.item.provider.postgres": "PostgresSQL",
|
||||
"form.database.item.provider.mysql": "MySQL",
|
||||
"form.database.item.provider.sqlite3": "SQlite3",
|
||||
"form.database.item.provider.redis": "Redis",
|
||||
|
||||
"form.application.name": "Application",
|
||||
|
||||
@ -34,7 +34,6 @@
|
||||
"form.database.item.provider.mongo": "Mongo",
|
||||
"form.database.item.provider.postgres": "PostgresSQL",
|
||||
"form.database.item.provider.mysql": "MySQL",
|
||||
"form.database.item.provider.sqlite3": "SQlite3",
|
||||
"form.database.item.provider.redis": "Redis",
|
||||
|
||||
"form.application.name": "Application",
|
||||
|
||||
@ -34,7 +34,6 @@
|
||||
"form.database.item.provider.mongo": "Mongo",
|
||||
"form.database.item.provider.postgres": "PostgresSQL",
|
||||
"form.database.item.provider.mysql": "MySQL",
|
||||
"form.database.item.provider.sqlite3": "SQlite3",
|
||||
"form.database.item.provider.redis": "Redis",
|
||||
|
||||
"form.application.name": "Aplikacja",
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@ -34,7 +34,6 @@
|
||||
"form.database.item.provider.mongo": "Mongo",
|
||||
"form.database.item.provider.postgres": "PostgresSQL",
|
||||
"form.database.item.provider.mysql": "MySQL",
|
||||
"form.database.item.provider.sqlite3": "SQlite3",
|
||||
"form.database.item.provider.redis": "Redis",
|
||||
|
||||
"form.application.name": "Uygulama",
|
||||
|
||||
@ -0,0 +1,655 @@
|
||||
{
|
||||
"components.DownloadDb.download": "正在安装...",
|
||||
"components.DownloadDb.text": "这可能需要几分钟左右。谢谢你的耐心。",
|
||||
"plugin.description.short": "在几秒钟内配置你的项目。",
|
||||
"plugin.description.long": "在几秒钟内配置你的项目。",
|
||||
"menu.section.global-settings": "全局设置",
|
||||
"menu.item.application": "应用",
|
||||
"menu.item.languages": "语言",
|
||||
"menu.item.advanced": "高级",
|
||||
|
||||
"menu.section.environments": "环境",
|
||||
"menu.item.database": "数据库",
|
||||
"menu.item.request": "请求",
|
||||
"menu.item.response": "回复",
|
||||
"menu.item.security": "安全性",
|
||||
"menu.item.server": "服务器",
|
||||
|
||||
"form.button.cancel": "取消",
|
||||
"form.button.save": "保存",
|
||||
"form.button.confirm": "确认",
|
||||
|
||||
"form.databases.name": "数据库",
|
||||
"form.databases.description": "通过环境配置数据库设置。",
|
||||
|
||||
"form.database.item.name": "连接名",
|
||||
"form.database.item.client": "客户端",
|
||||
"form.database.item.connector": "连接器",
|
||||
"form.database.item.host": "主机",
|
||||
"form.database.item.port": "端口",
|
||||
"form.database.item.username": "用户名",
|
||||
"form.database.item.password": "密码",
|
||||
"form.database.item.database": "数据库",
|
||||
"form.database.item.default": "设置为默认连接",
|
||||
"form.database.item.provider.mongo": "Mongo",
|
||||
"form.database.item.provider.postgres": "PostgresSQL",
|
||||
"form.database.item.provider.mysql": "MySQL",
|
||||
"form.database.item.provider.sqlite3": "SQlite3",
|
||||
"form.database.item.provider.redis": "Redis",
|
||||
|
||||
"form.application.name": "应用",
|
||||
"form.application.description": "配置应用程序设置。",
|
||||
|
||||
"form.application.item.name": "名字",
|
||||
"form.application.item.description": "描述",
|
||||
"form.application.item.version": "版本",
|
||||
|
||||
"form.advanced.name": "先进的",
|
||||
"form.advanced.description": "配置高级设置。",
|
||||
|
||||
"form.advanced.item.admin": "Admin dashboard url",
|
||||
"form.advanced.item.prefix": "Prefix API",
|
||||
|
||||
"form.request.name": "Request",
|
||||
"form.request.description": "配置您的请求设置。",
|
||||
"form.request.item.parser": "Parser",
|
||||
"form.request.item.parser.multipart": "Parser Multipart",
|
||||
"form.request.item.prefix": "Prefix",
|
||||
"form.request.item.prefix.prefix": "Prefix",
|
||||
"form.request.item.logger": "Logger",
|
||||
"form.request.item.logger.level": "Level",
|
||||
"form.request.item.logger.exposeInContext": "Expose in context",
|
||||
"form.request.item.logger.requests": "Requests",
|
||||
"form.request.item.router": "Router",
|
||||
"form.request.item.router.prefix": "Prefix",
|
||||
|
||||
"form.response.name": "Response",
|
||||
"form.response.description": "配置您的响应设置。",
|
||||
"form.response.item.gzip.enabled": "Gzip",
|
||||
"form.response.item.responseTime.enabled": "Response Time",
|
||||
|
||||
"form.security.name": "Security",
|
||||
"form.security.description": "配置安全设置。",
|
||||
|
||||
"form.security.item.csrf": "CSRF",
|
||||
"form.security.item.p3p": "P3P",
|
||||
"form.security.item.p3p.value": "Value",
|
||||
"form.security.item.hsts": "HOSTS",
|
||||
"form.security.item.csrf.key": "Key",
|
||||
"form.security.item.csrf.secret": "Secret",
|
||||
"form.security.item.csrf.cookie": "Cookie",
|
||||
"form.security.item.csrf.angular": "Angular",
|
||||
"form.security.item.hsts.maxAge": "Max Age",
|
||||
"form.security.item.hsts.includeSubDomains": "包括子域",
|
||||
"form.security.item.hsts.preload": "Preload",
|
||||
|
||||
"form.security.item.session": "Session",
|
||||
"form.security.item.session.key": "Secret key",
|
||||
"form.security.item.session.maxAge": "Maximum age",
|
||||
|
||||
"form.security.item.xframe": "Xframe",
|
||||
"form.security.item.xframe.value": "Options",
|
||||
"form.security.item.xframe.deny": "DENY",
|
||||
"form.security.item.xframe.sameorigin": "SAMEORIGIN",
|
||||
"form.security.item.xframe.allow-from": "ALLOW-FROM",
|
||||
|
||||
"form.security.item.xssProtection": "xss Protection",
|
||||
"form.security.item.xssProtection.mode": "Mode",
|
||||
|
||||
"form.security.item.cors": "Cors",
|
||||
"form.security.item.cors.origin": "Origin",
|
||||
|
||||
"form.server.name": "Server",
|
||||
"form.server.description": "配置服务器设置。",
|
||||
|
||||
"form.server.item.host": "Host",
|
||||
"form.server.item.port": "Port",
|
||||
"form.server.item.cron": "Cron",
|
||||
|
||||
"form.language.name": "Languages",
|
||||
"form.language.description": "配置您的语言。",
|
||||
"form.language.choose": "选择一种语言:",
|
||||
|
||||
"request.error.database.exist": "此连接已经存在",
|
||||
"request.error.database.unknow": "没有这样的连接",
|
||||
"request.error.type.string": "需要一个文本。",
|
||||
"request.error.type.number": "需要一个数字。",
|
||||
"request.error.type.boolean": "需要一个布尔值。",
|
||||
"request.error.type.select": "该值必须在预定义列表中。",
|
||||
|
||||
"request.error.validation.required": "必选",
|
||||
"request.error.validation.regex": "格式错误",
|
||||
"request.error.validation.max": "超过最大值",
|
||||
"request.error.validation.min": "小于最小值",
|
||||
"request.error.validation.maxLength": "超过最大长度",
|
||||
"request.error.validation.minLength": "低于最小长度",
|
||||
|
||||
"request.error.config": "配置文件不存在。",
|
||||
"request.error.environment.required": "环境是必需的。",
|
||||
"request.error.environment.unknow": "环境未知。",
|
||||
"request.error.languages.exist": "这种语言已经存在。",
|
||||
"request.error.languages.unknow": "这种语言是不存在的。",
|
||||
"request.error.languages.incorrect": "这种语言不正确。",
|
||||
|
||||
"list.languages.button.label": "添加新语言",
|
||||
"list.languages.title.singular": "语言是可用的",
|
||||
"list.languages.title.plural": "可用的语言",
|
||||
"list.languages.default.languages": "缺省语言",
|
||||
"list.languages.set.languages": "设置为默认值",
|
||||
"list.databases.button.label": "添加新连接",
|
||||
"list.databases.title.singular": "在这种环境中的连接",
|
||||
"list.databases.title.plural": "在这种环境中的连接",
|
||||
|
||||
"popUpWarning.title": "请确认",
|
||||
"popUpWarning.databases.danger.message": "内容类型仍然与此连接连接。如果删除它,可能会对应用程序造成严重的问题。小心...",
|
||||
"popUpWarning.danger.ok.message": "我明白",
|
||||
"popUpWarning.databases.delete.message": "确实要删除此数据库吗?",
|
||||
"popUpWarning.languages.delete.message": "确实要删除此数据库吗?",
|
||||
"strapi.notification.info.settingsEqual": "设置相等",
|
||||
"strapi.notification.success.databaseDelete": "数据库已被成功删除。",
|
||||
"strapi.notification.success.languageDelete": "数据库已被成功删除。",
|
||||
"strapi.notification.success.languageAdd": "该语言已成功添加。",
|
||||
"strapi.notification.success.databaseAdd": "该语言已成功添加。",
|
||||
"strapi.notification.success.databaseEdit": "数据库设置已成功更新。",
|
||||
"strapi.notification.success.databaseDeleted": "数据库已被删除。",
|
||||
"strapi.notification.success.settingsEdit": "设置已成功更新。",
|
||||
"strapi.notification.error": "发生错误",
|
||||
"strapi.notification.info.serverRestart": "服务器将重新启动",
|
||||
|
||||
"language.af": "Afrikaans",
|
||||
"language.af_NA": "Afrikaans (Namibië)",
|
||||
"language.af_ZA": "Afrikaans (Suid-Afrika)",
|
||||
"language.agq": "Aghem",
|
||||
"language.agq_CM": "Aghem (Kàmàlûŋ)",
|
||||
"language.ak": "Akan",
|
||||
"language.ak_GH": "Akan (Gaana)",
|
||||
"language.am": "አማርኛ",
|
||||
"language.am_ET": "አማርኛ (ኢትዮጵያ)",
|
||||
"language.ar": "العربية",
|
||||
"language.ar_001": "العربية (العالم)",
|
||||
"language.ar_AE": "العربية (الإمارات العربية المتحدة)",
|
||||
"language.ar_BH": "العربية (البحرين)",
|
||||
"language.ar_DZ": "العربية (الجزائر)",
|
||||
"language.ar_EG": "العربية (مصر)",
|
||||
"language.ar_IQ": "العربية (العراق)",
|
||||
"language.ar_JO": "العربية (الأردن)",
|
||||
"language.ar_KW": "العربية (الكويت)",
|
||||
"language.ar_LB": "العربية (لبنان)",
|
||||
"language.ar_LY": "العربية (ليبيا)",
|
||||
"language.ar_MA": "العربية (المغرب)",
|
||||
"language.ar_OM": "العربية (عُمان)",
|
||||
"language.ar_QA": "العربية (قطر)",
|
||||
"language.ar_SA": "العربية (المملكة العربية السعودية)",
|
||||
"language.ar_SD": "العربية (السودان)",
|
||||
"language.ar_SY": "العربية (سوريا)",
|
||||
"language.ar_TN": "العربية (تونس)",
|
||||
"language.ar_YE": "العربية (اليمن)",
|
||||
"language.as": "অসমীয়া",
|
||||
"language.as_IN": "অসমীয়া (ভাৰত)",
|
||||
"language.asa": "Kipare",
|
||||
"language.asa_TZ": "Kipare (Tadhania)",
|
||||
"language.az": "azərbaycanca",
|
||||
"language.az_Cyrl": "Азәрбајҹан (kiril)",
|
||||
"language.az_Cyrl_AZ": "Азәрбајҹан (kiril, Азәрбајҹан)",
|
||||
"language.az_Latn": "azərbaycanca (latın)",
|
||||
"language.az_Latn_AZ": "azərbaycanca (latın, Azərbaycan)",
|
||||
"language.bas": "Ɓàsàa",
|
||||
"language.bas_CM": "Ɓàsàa (Kàmɛ̀rûn)",
|
||||
"language.be": "беларуская",
|
||||
"language.be_BY": "беларуская (Беларусь)",
|
||||
"language.bem": "Ichibemba",
|
||||
"language.bem_ZM": "Ichibemba (Zambia)",
|
||||
"language.bez": "Hibena",
|
||||
"language.bez_TZ": "Hibena (Hutanzania)",
|
||||
"language.bg": "български",
|
||||
"language.bg_BG": "български (България)",
|
||||
"language.bm": "bamanakan",
|
||||
"language.bm_ML": "bamanakan (Mali)",
|
||||
"language.bn": "বাংলা",
|
||||
"language.bn_BD": "বাংলা (বাংলাদেশ)",
|
||||
"language.bn_IN": "বাংলা (ভারত)",
|
||||
"language.bo": "པོད་སྐད་",
|
||||
"language.bo_CN": "པོད་སྐད་ (རྒྱ་ནག)",
|
||||
"language.bo_IN": "པོད་སྐད་ (རྒྱ་གར་)",
|
||||
"language.br": "brezhoneg",
|
||||
"language.br_FR": "brezhoneg (Frañs)",
|
||||
"language.brx": "बड़ो",
|
||||
"language.brx_IN": "बड़ो (भारत)",
|
||||
"language.bs": "bosanski",
|
||||
"language.bs_BA": "bosanski (Bosna i Hercegovina)",
|
||||
"language.ca": "català",
|
||||
"language.ca_ES": "català (Espanya)",
|
||||
"language.cgg": "Rukiga",
|
||||
"language.cgg_UG": "Rukiga (Uganda)",
|
||||
"language.chr": "ᏣᎳᎩ",
|
||||
"language.chr_US": "ᏣᎳᎩ (ᎠᎹᏰᏟ)",
|
||||
"language.cs": "čeština",
|
||||
"language.cs_CZ": "čeština (Česká republika)",
|
||||
"language.cy": "Cymraeg",
|
||||
"language.cy_GB": "Cymraeg (Prydain Fawr)",
|
||||
"language.da": "dansk",
|
||||
"language.da_DK": "dansk (Danmark)",
|
||||
"language.dav": "Kitaita",
|
||||
"language.dav_KE": "Kitaita (Kenya)",
|
||||
"language.de": "Deutsch",
|
||||
"language.de_AT": "Deutsch (Österreich)",
|
||||
"language.de_BE": "Deutsch (Belgien)",
|
||||
"language.de_CH": "Deutsch (Schweiz)",
|
||||
"language.de_DE": "Deutsch (Deutschland)",
|
||||
"language.de_LI": "Deutsch (Liechtenstein)",
|
||||
"language.de_LU": "Deutsch (Luxemburg)",
|
||||
"language.dje": "Zarmaciine",
|
||||
"language.dje_NE": "Zarmaciine (Nižer)",
|
||||
"language.dua": "duálá",
|
||||
"language.dua_CM": "duálá (Cameroun)",
|
||||
"language.dyo": "joola",
|
||||
"language.dyo_SN": "joola (Senegal)",
|
||||
"language.ebu": "Kĩembu",
|
||||
"language.ebu_KE": "Kĩembu (Kenya)",
|
||||
"language.ee": "eʋegbe",
|
||||
"language.ee_GH": "eʋegbe (Ghana nutome)",
|
||||
"language.ee_TG": "eʋegbe (Togo nutome)",
|
||||
"language.el": "Ελληνικά",
|
||||
"language.el_CY": "Ελληνικά (Κύπρος)",
|
||||
"language.el_GR": "Ελληνικά (Ελλάδα)",
|
||||
"language.en": "English",
|
||||
"language.en_AS": "English (American Samoa)",
|
||||
"language.en_AU": "English (Australia)",
|
||||
"language.en_BB": "English (Barbados)",
|
||||
"language.en_BE": "English (Belgium)",
|
||||
"language.en_BM": "English (Bermuda)",
|
||||
"language.en_BW": "English (Botswana)",
|
||||
"language.en_BZ": "English (Belize)",
|
||||
"language.en_CA": "English (Canada)",
|
||||
"language.en_GB": "English (United Kingdom)",
|
||||
"language.en_GU": "English (Guam)",
|
||||
"language.en_GY": "English (Guyana)",
|
||||
"language.en_HK": "English (Hong Kong SAR China)",
|
||||
"language.en_IE": "English (Ireland)",
|
||||
"language.en_IN": "English (India)",
|
||||
"language.en_JM": "English (Jamaica)",
|
||||
"language.en_MH": "English (Marshall Islands)",
|
||||
"language.en_MP": "English (Northern Mariana Islands)",
|
||||
"language.en_MT": "English (Malta)",
|
||||
"language.en_MU": "English (Mauritius)",
|
||||
"language.en_NA": "English (Namibia)",
|
||||
"language.en_NZ": "English (New Zealand)",
|
||||
"language.en_PH": "English (Philippines)",
|
||||
"language.en_PK": "English (Pakistan)",
|
||||
"language.en_SG": "English (Singapore)",
|
||||
"language.en_TT": "English (Trinidad and Tobago)",
|
||||
"language.en_UM": "English (U.S. Minor Outlying Islands)",
|
||||
"language.en_US": "English (United States)",
|
||||
"language.en_US_POSIX": "English (United States, Computer)",
|
||||
"language.en_VI": "English (U.S. Virgin Islands)",
|
||||
"language.en_ZA": "English (South Africa)",
|
||||
"language.en_ZW": "English (Zimbabwe)",
|
||||
"language.eo": "esperanto",
|
||||
"language.es": "español",
|
||||
"language.es_419": "español (Latinoamérica)",
|
||||
"language.es_AR": "español (Argentina)",
|
||||
"language.es_BO": "español (Bolivia)",
|
||||
"language.es_CL": "español (Chile)",
|
||||
"language.es_CO": "español (Colombia)",
|
||||
"language.es_CR": "español (Costa Rica)",
|
||||
"language.es_DO": "español (República Dominicana)",
|
||||
"language.es_EC": "español (Ecuador)",
|
||||
"language.es_ES": "español (España)",
|
||||
"language.es_GQ": "español (Guinea Ecuatorial)",
|
||||
"language.es_GT": "español (Guatemala)",
|
||||
"language.es_HN": "español (Honduras)",
|
||||
"language.es_MX": "español (México)",
|
||||
"language.es_NI": "español (Nicaragua)",
|
||||
"language.es_PA": "español (Panamá)",
|
||||
"language.es_PE": "español (Perú)",
|
||||
"language.es_PR": "español (Puerto Rico)",
|
||||
"language.es_PY": "español (Paraguay)",
|
||||
"language.es_SV": "español (El Salvador)",
|
||||
"language.es_US": "español (Estados Unidos)",
|
||||
"language.es_UY": "español (Uruguay)",
|
||||
"language.es_VE": "español (Venezuela)",
|
||||
"language.et": "eesti",
|
||||
"language.et_EE": "eesti (Eesti)",
|
||||
"language.eu": "euskara",
|
||||
"language.eu_ES": "euskara (Espainia)",
|
||||
"language.ewo": "ewondo",
|
||||
"language.ewo_CM": "ewondo (Kamǝrún)",
|
||||
"language.fa": "فارسی",
|
||||
"language.fa_AF": "دری (افغانستان)",
|
||||
"language.fa_IR": "فارسی (ایران)",
|
||||
"language.ff": "Pulaar",
|
||||
"language.ff_SN": "Pulaar (Senegaal)",
|
||||
"language.fi": "suomi",
|
||||
"language.fi_FI": "suomi (Suomi)",
|
||||
"language.fil": "Filipino",
|
||||
"language.fil_PH": "Filipino (Pilipinas)",
|
||||
"language.fo": "føroyskt",
|
||||
"language.fo_FO": "føroyskt (Føroyar)",
|
||||
"language.fr": "français",
|
||||
"language.fr_BE": "français (Belgique)",
|
||||
"language.fr_BF": "français (Burkina Faso)",
|
||||
"language.fr_BI": "français (Burundi)",
|
||||
"language.fr_BJ": "français (Bénin)",
|
||||
"language.fr_BL": "français (Saint-Barthélémy)",
|
||||
"language.fr_CA": "français (Canada)",
|
||||
"language.fr_CD": "français (République démocratique du Congo)",
|
||||
"language.fr_CF": "français (République centrafricaine)",
|
||||
"language.fr_CG": "français (Congo-Brazzaville)",
|
||||
"language.fr_CH": "français (Suisse)",
|
||||
"language.fr_CI": "français (Côte d’Ivoire)",
|
||||
"language.fr_CM": "français (Cameroun)",
|
||||
"language.fr_DJ": "français (Djibouti)",
|
||||
"language.fr_FR": "français (France)",
|
||||
"language.fr_GA": "français (Gabon)",
|
||||
"language.fr_GF": "français (Guyane française)",
|
||||
"language.fr_GN": "français (Guinée)",
|
||||
"language.fr_GP": "français (Guadeloupe)",
|
||||
"language.fr_GQ": "français (Guinée équatoriale)",
|
||||
"language.fr_KM": "français (Comores)",
|
||||
"language.fr_LU": "français (Luxembourg)",
|
||||
"language.fr_MC": "français (Monaco)",
|
||||
"language.fr_MF": "français (Saint-Martin)",
|
||||
"language.fr_MG": "français (Madagascar)",
|
||||
"language.fr_ML": "français (Mali)",
|
||||
"language.fr_MQ": "français (Martinique)",
|
||||
"language.fr_NE": "français (Niger)",
|
||||
"language.fr_RE": "français (Réunion)",
|
||||
"language.fr_RW": "français (Rwanda)",
|
||||
"language.fr_SN": "français (Sénégal)",
|
||||
"language.fr_TD": "français (Tchad)",
|
||||
"language.fr_TG": "français (Togo)",
|
||||
"language.fr_YT": "français (Mayotte)",
|
||||
"language.ga": "Gaeilge",
|
||||
"language.ga_IE": "Gaeilge (Éire)",
|
||||
"language.gl": "galego",
|
||||
"language.gl_ES": "galego (España)",
|
||||
"language.gsw": "Schwiizertüütsch",
|
||||
"language.gsw_CH": "Schwiizertüütsch (Schwiiz)",
|
||||
"language.gu": "ગુજરાતી",
|
||||
"language.gu_IN": "ગુજરાતી (ભારત)",
|
||||
"language.guz": "Ekegusii",
|
||||
"language.guz_KE": "Ekegusii (Kenya)",
|
||||
"language.gv": "Gaelg",
|
||||
"language.gv_GB": "Gaelg (Rywvaneth Unys)",
|
||||
"language.ha": "Hausa",
|
||||
"language.ha_Latn": "Hausa (Latn)",
|
||||
"language.ha_Latn_GH": "Hausa (Latn, Gana)",
|
||||
"language.ha_Latn_NE": "Hausa (Latn, Nijar)",
|
||||
"language.ha_Latn_NG": "Hausa (Latn, Najeriya)",
|
||||
"language.haw": "ʻŌlelo Hawaiʻi",
|
||||
"language.haw_US": "ʻŌlelo Hawaiʻi (ʻAmelika Hui Pū ʻIa)",
|
||||
"language.he": "עברית",
|
||||
"language.he_IL": "עברית (ישראל)",
|
||||
"language.hi": "हिन्दी",
|
||||
"language.hi_IN": "हिन्दी (भारत)",
|
||||
"language.hr": "hrvatski",
|
||||
"language.hr_HR": "hrvatski (Hrvatska)",
|
||||
"language.hu": "magyar",
|
||||
"language.hu_HU": "magyar (Magyarország)",
|
||||
"language.hy": "Հայերէն",
|
||||
"language.hy_AM": "Հայերէն (Հայաստանի Հանրապետութիւն)",
|
||||
"language.id": "Bahasa Indonesia",
|
||||
"language.id_ID": "Bahasa Indonesia (Indonesia)",
|
||||
"language.ig": "Igbo",
|
||||
"language.ig_NG": "Igbo (Nigeria)",
|
||||
"language.ii": "ꆈꌠꉙ",
|
||||
"language.ii_CN": "ꆈꌠꉙ (ꍏꇩ)",
|
||||
"language.is": "íslenska",
|
||||
"language.is_IS": "íslenska (Ísland)",
|
||||
"language.it": "italiano",
|
||||
"language.it_CH": "italiano (Svizzera)",
|
||||
"language.it_IT": "italiano (Italia)",
|
||||
"language.ja": "日本語",
|
||||
"language.ja_JP": "日本語(日本)",
|
||||
"language.jmc": "Kimachame",
|
||||
"language.jmc_TZ": "Kimachame (Tanzania)",
|
||||
"language.ka": "ქართული",
|
||||
"language.ka_GE": "ქართული (საქართველო)",
|
||||
"language.kab": "Taqbaylit",
|
||||
"language.kab_DZ": "Taqbaylit (Lezzayer)",
|
||||
"language.kam": "Kikamba",
|
||||
"language.kam_KE": "Kikamba (Kenya)",
|
||||
"language.kde": "Chimakonde",
|
||||
"language.kde_TZ": "Chimakonde (Tanzania)",
|
||||
"language.kea": "kabuverdianu",
|
||||
"language.kea_CV": "kabuverdianu (Kabu Verdi)",
|
||||
"language.khq": "Koyra ciini",
|
||||
"language.khq_ML": "Koyra ciini (Maali)",
|
||||
"language.ki": "Gikuyu",
|
||||
"language.ki_KE": "Gikuyu (Kenya)",
|
||||
"language.kk": "қазақ тілі",
|
||||
"language.kk_Cyrl": "қазақ тілі (кириллица)",
|
||||
"language.kk_Cyrl_KZ": "қазақ тілі (кириллица, Қазақстан)",
|
||||
"language.kl": "kalaallisut",
|
||||
"language.kl_GL": "kalaallisut (Kalaallit Nunaat)",
|
||||
"language.kln": "Kalenjin",
|
||||
"language.kln_KE": "Kalenjin (Emetab Kenya)",
|
||||
"language.km": "ភាសាខ្មែរ",
|
||||
"language.km_KH": "ភាសាខ្មែរ (កម្ពុជា)",
|
||||
"language.kn": "ಕನ್ನಡ",
|
||||
"language.kn_IN": "ಕನ್ನಡ (ಭಾರತ)",
|
||||
"language.ko": "한국어",
|
||||
"language.ko_KR": "한국어(대한민국)",
|
||||
"language.kok": "कोंकणी",
|
||||
"language.kok_IN": "कोंकणी (भारत)",
|
||||
"language.ksb": "Kishambaa",
|
||||
"language.ksb_TZ": "Kishambaa (Tanzania)",
|
||||
"language.ksf": "rikpa",
|
||||
"language.ksf_CM": "rikpa (kamɛrún)",
|
||||
"language.kw": "kernewek",
|
||||
"language.kw_GB": "kernewek (Rywvaneth Unys)",
|
||||
"language.lag": "Kɨlaangi",
|
||||
"language.lag_TZ": "Kɨlaangi (Taansanía)",
|
||||
"language.lg": "Luganda",
|
||||
"language.lg_UG": "Luganda (Yuganda)",
|
||||
"language.ln": "lingála",
|
||||
"language.ln_CD": "lingála (Repibiki demokratiki ya Kongó)",
|
||||
"language.ln_CG": "lingála (Kongo)",
|
||||
"language.lt": "lietuvių",
|
||||
"language.lt_LT": "lietuvių (Lietuva)",
|
||||
"language.lu": "Tshiluba",
|
||||
"language.lu_CD": "Tshiluba (Ditunga wa Kongu)",
|
||||
"language.luo": "Dholuo",
|
||||
"language.luo_KE": "Dholuo (Kenya)",
|
||||
"language.luy": "Luluhia",
|
||||
"language.luy_KE": "Luluhia (Kenya)",
|
||||
"language.lv": "latviešu",
|
||||
"language.lv_LV": "latviešu (Latvija)",
|
||||
"language.mas": "Maa",
|
||||
"language.mas_KE": "Maa (Kenya)",
|
||||
"language.mas_TZ": "Maa (Tansania)",
|
||||
"language.mer": "Kĩmĩrũ",
|
||||
"language.mer_KE": "Kĩmĩrũ (Kenya)",
|
||||
"language.mfe": "kreol morisien",
|
||||
"language.mfe_MU": "kreol morisien (Moris)",
|
||||
"language.mg": "Malagasy",
|
||||
"language.mg_MG": "Malagasy (Madagasikara)",
|
||||
"language.mgh": "Makua",
|
||||
"language.mgh_MZ": "Makua (Umozambiki)",
|
||||
"language.mk": "македонски",
|
||||
"language.mk_MK": "македонски (Македонија)",
|
||||
"language.ml": "മലയാളം",
|
||||
"language.ml_IN": "മലയാളം (ഇന്ത്യ)",
|
||||
"language.mr": "मराठी",
|
||||
"language.mr_IN": "मराठी (भारत)",
|
||||
"language.ms": "Bahasa Melayu",
|
||||
"language.ms_BN": "Bahasa Melayu (Brunei)",
|
||||
"language.ms_MY": "Bahasa Melayu (Malaysia)",
|
||||
"language.mt": "Malti",
|
||||
"language.mt_MT": "Malti (Malta)",
|
||||
"language.mua": "MUNDAŊ",
|
||||
"language.mua_CM": "MUNDAŊ (kameruŋ)",
|
||||
"language.my": "ဗမာ",
|
||||
"language.my_MM": "ဗမာ (မြန်မာ)",
|
||||
"language.naq": "Khoekhoegowab",
|
||||
"language.naq_NA": "Khoekhoegowab (Namibiab)",
|
||||
"language.nb": "norsk bokmål",
|
||||
"language.nb_NO": "norsk bokmål (Norge)",
|
||||
"language.nd": "isiNdebele",
|
||||
"language.nd_ZW": "isiNdebele (Zimbabwe)",
|
||||
"language.ne": "नेपाली",
|
||||
"language.ne_IN": "नेपाली (भारत)",
|
||||
"language.ne_NP": "नेपाली (नेपाल)",
|
||||
"language.nl": "Nederlands",
|
||||
"language.nl_AW": "Nederlands (Aruba)",
|
||||
"language.nl_BE": "Nederlands (België)",
|
||||
"language.nl_CW": "Nederlands (Curaçao)",
|
||||
"language.nl_NL": "Nederlands (Nederland)",
|
||||
"language.nl_SX": "Nederlands (Sint Maarten)",
|
||||
"language.nmg": "nmg",
|
||||
"language.nmg_CM": "nmg (Kamerun)",
|
||||
"language.nn": "nynorsk",
|
||||
"language.nn_NO": "nynorsk (Noreg)",
|
||||
"language.nus": "Thok Nath",
|
||||
"language.nus_SD": "Thok Nath (Sudan)",
|
||||
"language.nyn": "Runyankore",
|
||||
"language.nyn_UG": "Runyankore (Uganda)",
|
||||
"language.om": "Oromoo",
|
||||
"language.om_ET": "Oromoo (Itoophiyaa)",
|
||||
"language.om_KE": "Oromoo (Keeniyaa)",
|
||||
"language.or": "ଓଡ଼ିଆ",
|
||||
"language.or_IN": "ଓଡ଼ିଆ (ଭାରତ)",
|
||||
"language.pa": "ਪੰਜਾਬੀ",
|
||||
"language.pa_Arab": "پنجاب (العربية)",
|
||||
"language.pa_Arab_PK": "پنجاب (العربية, پکستان)",
|
||||
"language.pa_Guru": "ਪੰਜਾਬੀ (Guru)",
|
||||
"language.pa_Guru_IN": "ਪੰਜਾਬੀ (Guru, ਭਾਰਤ)",
|
||||
"language.pl": "polski",
|
||||
"language.pl_PL": "polski (Polska)",
|
||||
"language.ps": "پښتو",
|
||||
"language.ps_AF": "پښتو (افغانستان)",
|
||||
"language.pt": "português",
|
||||
"language.pt_AO": "português (Angola)",
|
||||
"language.pt_BR": "português (Brasil)",
|
||||
"language.pt_GW": "português (Guiné Bissau)",
|
||||
"language.pt_MZ": "português (Moçambique)",
|
||||
"language.pt_PT": "português (Portugal)",
|
||||
"language.pt_ST": "português (São Tomé e Príncipe)",
|
||||
"language.rm": "rumantsch",
|
||||
"language.rm_CH": "rumantsch (Svizra)",
|
||||
"language.rn": "Ikirundi",
|
||||
"language.rn_BI": "Ikirundi (Uburundi)",
|
||||
"language.ro": "română",
|
||||
"language.ro_MD": "română (Republica Moldova)",
|
||||
"language.ro_RO": "română (România)",
|
||||
"language.rof": "Kihorombo",
|
||||
"language.rof_TZ": "Kihorombo (Tanzania)",
|
||||
"language.ru": "русский",
|
||||
"language.ru_MD": "русский (Молдова)",
|
||||
"language.ru_RU": "русский (Россия)",
|
||||
"language.ru_UA": "русский (Украина)",
|
||||
"language.rw": "Kinyarwanda",
|
||||
"language.rw_RW": "Kinyarwanda (Rwanda)",
|
||||
"language.rwk": "Kiruwa",
|
||||
"language.rwk_TZ": "Kiruwa (Tanzania)",
|
||||
"language.saq": "Kisampur",
|
||||
"language.saq_KE": "Kisampur (Kenya)",
|
||||
"language.sbp": "Ishisangu",
|
||||
"language.sbp_TZ": "Ishisangu (Tansaniya)",
|
||||
"language.seh": "sena",
|
||||
"language.seh_MZ": "sena (Moçambique)",
|
||||
"language.ses": "Koyraboro senni",
|
||||
"language.ses_ML": "Koyraboro senni (Maali)",
|
||||
"language.sg": "Sängö",
|
||||
"language.sg_CF": "Sängö (Ködörösêse tî Bêafrîka)",
|
||||
"language.shi": "tamazight",
|
||||
"language.shi_Latn": "tamazight (Latn)",
|
||||
"language.shi_Latn_MA": "tamazight (Latn, lmɣrib)",
|
||||
"language.shi_Tfng": "ⵜⴰⵎⴰⵣⵉⵖⵜ (Tfng)",
|
||||
"language.shi_Tfng_MA": "ⵜⴰⵎⴰⵣⵉⵖⵜ (Tfng, ⵍⵎⵖⵔⵉⴱ)",
|
||||
"language.si": "සිංහල",
|
||||
"language.si_LK": "සිංහල (ශ්රී ලංකාව)",
|
||||
"language.sk": "slovenčina",
|
||||
"language.sk_SK": "slovenčina (Slovenská republika)",
|
||||
"language.sl": "slovenščina",
|
||||
"language.sl_SI": "slovenščina (Slovenija)",
|
||||
"language.sn": "chiShona",
|
||||
"language.sn_ZW": "chiShona (Zimbabwe)",
|
||||
"language.so": "Soomaali",
|
||||
"language.so_DJ": "Soomaali (Jabuuti)",
|
||||
"language.so_ET": "Soomaali (Itoobiya)",
|
||||
"language.so_KE": "Soomaali (Kiiniya)",
|
||||
"language.so_SO": "Soomaali (Soomaaliya)",
|
||||
"language.sq": "shqip",
|
||||
"language.sq_AL": "shqip (Shqipëria)",
|
||||
"language.sr": "Српски",
|
||||
"language.sr_Cyrl": "Српски (Ћирилица)",
|
||||
"language.sr_Cyrl_BA": "Српски (Ћирилица, Босна и Херцеговина)",
|
||||
"language.sr_Cyrl_ME": "Српски (Ћирилица, Црна Гора)",
|
||||
"language.sr_Cyrl_RS": "Српски (Ћирилица, Србија)",
|
||||
"language.sr_Latn": "Srpski (Latinica)",
|
||||
"language.sr_Latn_BA": "Srpski (Latinica, Bosna i Hercegovina)",
|
||||
"language.sr_Latn_ME": "Srpski (Latinica, Crna Gora)",
|
||||
"language.sr_Latn_RS": "Srpski (Latinica, Srbija)",
|
||||
"language.sv": "svenska",
|
||||
"language.sv_FI": "svenska (Finland)",
|
||||
"language.sv_SE": "svenska (Sverige)",
|
||||
"language.sw": "Kiswahili",
|
||||
"language.sw_KE": "Kiswahili (Kenya)",
|
||||
"language.sw_TZ": "Kiswahili (Tanzania)",
|
||||
"language.swc": "Kiswahili ya Kongo",
|
||||
"language.swc_CD": "Kiswahili ya Kongo (Jamhuri ya Kidemokrasia ya Kongo)",
|
||||
"language.ta": "தமிழ்",
|
||||
"language.ta_IN": "தமிழ் (இந்தியா)",
|
||||
"language.ta_LK": "தமிழ் (இலங்கை)",
|
||||
"language.te": "తెలుగు",
|
||||
"language.te_IN": "తెలుగు (భారత దేశం)",
|
||||
"language.teo": "Kiteso",
|
||||
"language.teo_KE": "Kiteso (Kenia)",
|
||||
"language.teo_UG": "Kiteso (Uganda)",
|
||||
"language.th": "ไทย",
|
||||
"language.th_TH": "ไทย (ไทย)",
|
||||
"language.ti": "ትግርኛ",
|
||||
"language.ti_ER": "ትግርኛ (ER)",
|
||||
"language.ti_ET": "ትግርኛ (ET)",
|
||||
"language.to": "lea fakatonga",
|
||||
"language.to_TO": "lea fakatonga (Tonga)",
|
||||
"language.tr": "Türkçe",
|
||||
"language.tr_TR": "Türkçe (Türkiye)",
|
||||
"language.twq": "Tasawaq senni",
|
||||
"language.twq_NE": "Tasawaq senni (Nižer)",
|
||||
"language.tzm": "Tamaziɣt",
|
||||
"language.tzm_Latn": "Tamaziɣt (Latn)",
|
||||
"language.tzm_Latn_MA": "Tamaziɣt (Latn, Meṛṛuk)",
|
||||
"language.uk": "українська",
|
||||
"language.uk_UA": "українська (Україна)",
|
||||
"language.ur": "اردو",
|
||||
"language.ur_IN": "اردو (بھارت)",
|
||||
"language.ur_PK": "اردو (پاکستان)",
|
||||
"language.uz": "Ўзбек",
|
||||
"language.uz_Arab": "اۉزبېک (Arab)",
|
||||
"language.uz_Arab_AF": "اۉزبېک (Arab, افغانستان)",
|
||||
"language.uz_Cyrl": "Ўзбек (Cyrl)",
|
||||
"language.uz_Cyrl_UZ": "Ўзбек (Cyrl, Ўзбекистон)",
|
||||
"language.uz_Latn": "oʼzbekcha (Lotin)",
|
||||
"language.uz_Latn_UZ": "oʼzbekcha (Lotin, Oʼzbekiston)",
|
||||
"language.vai": "ꕙꔤ",
|
||||
"language.vai_Latn": "Vai (Latn)",
|
||||
"language.vai_Latn_LR": "Vai (Latn, Laibhiya)",
|
||||
"language.vai_Vaii": "ꕙꔤ (Vaii)",
|
||||
"language.vai_Vaii_LR": "ꕙꔤ (Vaii, ꕞꔤꔫꕩ)",
|
||||
"language.vi": "Tiếng Việt",
|
||||
"language.vi_VN": "Tiếng Việt (Việt Nam)",
|
||||
"language.vun": "Kyivunjo",
|
||||
"language.vun_TZ": "Kyivunjo (Tanzania)",
|
||||
"language.xog": "Olusoga",
|
||||
"language.xog_UG": "Olusoga (Yuganda)",
|
||||
"language.yav": "nuasue",
|
||||
"language.yav_CM": "nuasue (Kemelún)",
|
||||
"language.yo": "Èdè Yorùbá",
|
||||
"language.yo_NG": "Èdè Yorùbá (Orílẹ́ède Nàìjíríà)",
|
||||
"language.zh": "中文",
|
||||
"language.zh_Hans": "中文(简体中文)",
|
||||
"language.zh_Hans_CN": "中文(简体中文、中国)",
|
||||
"language.zh_Hans_HK": "中文(简体中文、中国香港特别行政区)",
|
||||
"language.zh_Hans_MO": "中文(简体中文、中国澳门特别行政区)",
|
||||
"language.zh_Hans_SG": "中文(简体中文、新加坡)",
|
||||
"language.zh_Hant": "中文(繁體中文)",
|
||||
"language.zh_Hant_HK": "中文(繁體中文,中華人民共和國香港特別行政區)",
|
||||
"language.zh_Hant_MO": "中文(繁體中文,中華人民共和國澳門特別行政區)",
|
||||
"language.zh_Hant_TW": "中文(繁體中文,台灣)",
|
||||
"language.zu": "isiZulu",
|
||||
"language.zu_ZA": "isiZulu (iNingizimu Afrika)",
|
||||
|
||||
"pageNotFound": "Page not found"
|
||||
}
|
||||
@ -34,7 +34,6 @@
|
||||
"form.database.item.provider.mongo": "Mongo",
|
||||
"form.database.item.provider.postgres": "PostgresSQL",
|
||||
"form.database.item.provider.mysql": "MySQL",
|
||||
"form.database.item.provider.sqlite3": "SQlite3",
|
||||
"form.database.item.provider.redis": "Redis",
|
||||
|
||||
"form.application.name": "應用程式",
|
||||
|
||||
@ -215,8 +215,10 @@ module.exports = {
|
||||
|
||||
if (params.database.connections) {
|
||||
const settings = _.assign(_.clone(strapi.config.environments[env].database.connections[name].settings), params.database.connections[name].settings);
|
||||
const options = _.assign(_.clone(strapi.config.environments[env].database.connections[name].options), params.database.connections[name].options);
|
||||
params = _.assign(_.clone(strapi.config.environments[env].database.connections[name]), params.database.connections[name]);
|
||||
params.settings = settings;
|
||||
params.options = options;
|
||||
}
|
||||
|
||||
delete params.name;
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "strapi-plugin-settings-manager",
|
||||
"version": "3.0.0-alpha.12",
|
||||
"version": "3.0.0-alpha.12.1.3",
|
||||
"description": "Strapi plugin to manage settings.",
|
||||
"strapi": {
|
||||
"name": "Settings Manager",
|
||||
@ -25,7 +25,7 @@
|
||||
"devDependencies": {
|
||||
"flag-icon-css": "^2.8.0",
|
||||
"react-select": "^1.0.0-rc.5",
|
||||
"strapi-helper-plugin": "3.0.0-alpha.12"
|
||||
"strapi-helper-plugin": "3.0.0-alpha.12.1.3"
|
||||
},
|
||||
"author": {
|
||||
"name": "Strapi team",
|
||||
|
||||
@ -11,7 +11,7 @@ module.exports = {
|
||||
{
|
||||
name: 'menu.section.global-settings',
|
||||
items: [
|
||||
{
|
||||
{
|
||||
slug: 'application',
|
||||
name: 'menu.item.application',
|
||||
icon: 'globe'
|
||||
@ -105,7 +105,7 @@ module.exports = {
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
};
|
||||
},
|
||||
|
||||
request: env => ({
|
||||
@ -520,11 +520,6 @@ module.exports = {
|
||||
value: 'mysql',
|
||||
port: 3306
|
||||
},
|
||||
{
|
||||
name: 'form.database.item.provider.sqlite3',
|
||||
value: 'sqlite3',
|
||||
port: 1433
|
||||
},
|
||||
{
|
||||
name: 'form.database.item.provider.redis',
|
||||
value: 'redis',
|
||||
@ -575,7 +570,21 @@ module.exports = {
|
||||
type: 'password',
|
||||
value: _.get(strapi.config, `environments.${env}.database.connections.${name}.settings.password`, null),
|
||||
validations: {}
|
||||
}
|
||||
},
|
||||
{
|
||||
name: 'form.database.item.authenticationDatabase',
|
||||
target: `database.connections.${name}.options.authenticationDatabase`,
|
||||
type: 'string',
|
||||
value: _.get(strapi.config, `environments.${env}.database.connections.${name}.options.authenticationDatabase`, null),
|
||||
validations: {}
|
||||
},
|
||||
{
|
||||
name: 'form.database.item.ssl',
|
||||
target: `database.connections.${name}.options.ssl`,
|
||||
type: 'boolean',
|
||||
value: [true, 'true'].includes(_.get(strapi.config, `environments.${env}.database.connections.${name}.options.ssl`, false)),
|
||||
validations: {}
|
||||
},
|
||||
]
|
||||
},
|
||||
{
|
||||
@ -583,7 +592,7 @@ module.exports = {
|
||||
items: [
|
||||
{
|
||||
name: 'form.database.item.default',
|
||||
target: `database.defaultConnection`,
|
||||
target: 'database.defaultConnection',
|
||||
type: 'string',
|
||||
value: _.get(strapi.config, `environments.${env}.database.defaultConnection`, null),
|
||||
validations: {
|
||||
@ -636,7 +645,7 @@ module.exports = {
|
||||
},
|
||||
|
||||
getClientConnector: client => {
|
||||
const bookshelfClients = ['postgres', 'mysql', 'sqlite3'];
|
||||
const bookshelfClients = ['postgres', 'mysql'];
|
||||
const mongooseClients = ['mongo'];
|
||||
const redisClients = ['redis'];
|
||||
|
||||
@ -662,9 +671,6 @@ module.exports = {
|
||||
case 'mongo':
|
||||
return '#43b121';
|
||||
break;
|
||||
case 'sqlite3':
|
||||
return '#006fff';
|
||||
break;
|
||||
default:
|
||||
return '#000000';
|
||||
}
|
||||
@ -885,8 +891,7 @@ module.exports = {
|
||||
installDependency: (params, name) => {
|
||||
const clientsDependencies = {
|
||||
postgres: 'pg',
|
||||
mysql: 'mysql',
|
||||
sqlite3: 'sqlite3'
|
||||
mysql: 'mysql'
|
||||
};
|
||||
|
||||
const client = _.get(clientsDependencies, _.get(params, `database.connections.${name}.settings.client`));
|
||||
|
||||
@ -0,0 +1,36 @@
|
||||
{
|
||||
"ConfigPage.title": "上传-设置",
|
||||
"ConfigPage.description": "配置上传插件",
|
||||
|
||||
"EditForm.Input.number.label": "最大文件限制 (单位:MB)",
|
||||
"EditForm.Input.select.label": "Providers",
|
||||
"EditForm.Input.select.inputDescription": "文件可以上传到服务器上,也可以上传到外部存储服务供应商。",
|
||||
"EditForm.Input.toggle.label": "启用文件上传",
|
||||
|
||||
"EmptyLi.message": "没有上传的文件",
|
||||
|
||||
"EntriesNumber.number": "找到 {number} 个文件",
|
||||
"EntriesNumber.number.plural": "找到 {number} 个文件",
|
||||
|
||||
"HomePage.title": "上传",
|
||||
"HomePage.description": "发现所有上传的文件",
|
||||
"HomePage.InputSearch.placeholder": "搜索文件…",
|
||||
|
||||
"Li.linkCopied": "链接复制到剪贴板",
|
||||
|
||||
"ListHeader.type": "类型",
|
||||
"ListHeader.hash": "Hash",
|
||||
"ListHeader.name": "文件名",
|
||||
"ListHeader.updated": "更新时间",
|
||||
"ListHeader.size": "大小",
|
||||
"ListHeader.related": "Related to",
|
||||
|
||||
"PluginInputFile.text": "将文件拖放到该区域或 {link} 文件上传",
|
||||
"PluginInputFile.link": "浏览",
|
||||
"PluginInputFile.loading": "您的文件正在上传…",
|
||||
|
||||
"notification.config.success": "设置已更新",
|
||||
"notification.delete.success": "文件已被删除",
|
||||
"notification.dropFile.success": "您的文件已上传",
|
||||
"notification.dropFiles.success": "{number} 个文件已上传"
|
||||
}
|
||||
@ -13,48 +13,6 @@ const fs = require('fs');
|
||||
const _ = require('lodash');
|
||||
|
||||
module.exports = async cb => {
|
||||
const Model = strapi.plugins.upload.models.file;
|
||||
|
||||
if (Model.orm === 'bookshelf') {
|
||||
const hasTable = await strapi.connections[Model.connection].schema.hasTable(Model.tableName || Model.collectionName);
|
||||
|
||||
if (!hasTable) {
|
||||
const quote = Model.client === 'pg' ? '"' : '`';
|
||||
|
||||
strapi.log.warn(`
|
||||
⚠️ TABLE \`upload_file\` DOESN'T EXIST
|
||||
⚠️ TABLE \`upload_file_morph\` DOESN'T EXIST
|
||||
|
||||
CREATE TABLE ${quote}${Model.tableName || Model.collectionName}${quote} (
|
||||
id ${Model.client === 'pg' ? 'SERIAL' : 'INT AUTO_INCREMENT'} NOT NULL PRIMARY KEY,
|
||||
name text,
|
||||
hash text,
|
||||
ext text,
|
||||
mime text,
|
||||
size text,
|
||||
url text,
|
||||
provider text,
|
||||
updated_at ${Model.client === 'pg' ? 'timestamp with time zone' : 'timestamp DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP'},
|
||||
created_at ${Model.client === 'pg' ? 'timestamp with time zone' : 'timestamp DEFAULT CURRENT_TIMESTAMP'}
|
||||
);
|
||||
|
||||
CREATE TABLE ${quote}upload_file_morph${quote} (
|
||||
id ${Model.client === 'pg' ? 'SERIAL' : 'INT AUTO_INCREMENT'} NOT NULL PRIMARY KEY,
|
||||
upload_file_id ${Model.client === 'pg' ? 'integer' : 'int'},
|
||||
related_id ${Model.client === 'pg' ? 'integer' : 'int'},
|
||||
related_type text,
|
||||
field text
|
||||
);
|
||||
|
||||
1️⃣ EXECUTE THE FOLLOWING SQL QUERY
|
||||
|
||||
2️⃣ RESTART YOUR SERVER
|
||||
`);
|
||||
|
||||
strapi.stop();
|
||||
}
|
||||
}
|
||||
|
||||
// set plugin store
|
||||
const pluginStore = strapi.store({
|
||||
environment: strapi.config.environment,
|
||||
|
||||
@ -28,7 +28,7 @@
|
||||
"required": true
|
||||
},
|
||||
"size": {
|
||||
"type": "float",
|
||||
"type": "string",
|
||||
"configurable": false,
|
||||
"required": true
|
||||
},
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "strapi-plugin-upload",
|
||||
"version": "3.0.0-alpha.12",
|
||||
"version": "3.0.0-alpha.12.1.3",
|
||||
"description": "This is the description of the plugin.",
|
||||
"strapi": {
|
||||
"name": "Files Upload",
|
||||
@ -23,12 +23,12 @@
|
||||
},
|
||||
"dependencies": {
|
||||
"react-copy-to-clipboard": "^5.0.1",
|
||||
"strapi-upload-local": "3.0.0-alpha.12",
|
||||
"strapi-upload-local": "3.0.0-alpha.12.1.3",
|
||||
"stream-to-array": "^2.3.0",
|
||||
"uuid": "^3.2.1"
|
||||
},
|
||||
"devDependencies": {
|
||||
"strapi-helper-plugin": "3.0.0-alpha.12"
|
||||
"strapi-helper-plugin": "3.0.0-alpha.12.1.3"
|
||||
},
|
||||
"author": {
|
||||
"name": "A Strapi developer",
|
||||
@ -47,4 +47,4 @@
|
||||
"npm": ">= 3.0.0"
|
||||
},
|
||||
"license": "MIT"
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,177 @@
|
||||
{
|
||||
"Auth.form.button.register-success": "再次发送",
|
||||
"Auth.form.button.forgot-password.success": "再次发送",
|
||||
"Auth.form.button.forgot-password": "发送电子邮件",
|
||||
"Auth.form.button.reset-password": "修改密码",
|
||||
"Auth.form.button.login": "登陆",
|
||||
"Auth.form.button.register": "准备开始",
|
||||
"Auth.form.error.noAdminAccess": "你无法访问管理面板。",
|
||||
|
||||
"Auth.form.forgot-password.email.label": "输入你的电子邮件",
|
||||
"Auth.form.forgot-password.email.label.success": "电子邮件已成功发送到",
|
||||
"Auth.form.forgot-password.email.placeholder": "mysuperemail@gmail.com",
|
||||
|
||||
"Auth.header.register.description": "要完成安装并保护您的应用程序,请通过输入必要的信息来创建第一个用户(root管理员)。",
|
||||
"Auth.form.header.login": "strapi",
|
||||
"Auth.form.header.forgot-password": "strapi",
|
||||
"Auth.form.header.register": "欢迎!",
|
||||
"Auth.form.header.register-success": "strapi",
|
||||
|
||||
"Auth.form.login.password.label": "密码",
|
||||
"Auth.form.login.rememberMe.label": "记住我",
|
||||
"Auth.form.login.username.label": "用户名",
|
||||
"Auth.form.login.username.placeholder": "John Doe",
|
||||
|
||||
"Auth.form.register.email.label": "邮箱",
|
||||
"Auth.form.register.email.placeholder": "johndoe@gmail.com",
|
||||
"Auth.form.register.username.label": "用户名",
|
||||
"Auth.form.register.username.placeholder": "John Doe",
|
||||
"Auth.form.register.password.label": "密码",
|
||||
"Auth.form.register.confirmPassword.label": "确认密码",
|
||||
"Auth.form.register.news.label": "让我了解新特性和即将到来的改进。",
|
||||
|
||||
"Auth.form.register-success.email.label": "电子邮件已发送成功到",
|
||||
"Auth.form.register-success.email.placeholder": "mysuperemail@gmail.com",
|
||||
|
||||
"Auth.form.error.email.provide": "请提供您的用户名或电子邮件。",
|
||||
"Auth.form.error.email.invalid": "此电子邮件无效。",
|
||||
"Auth.form.error.password.provide": "请提供您的密码。",
|
||||
"Auth.form.error.invalid": "标识符或密码无效。",
|
||||
"Auth.form.error.password.local": "此用户从未设置本地密码,请通过帐户创建过程中使用的第三方供应商登录。",
|
||||
"Auth.form.error.password.format": "您的密码不能包含符号 `$` 超过三次。",
|
||||
"Auth.form.error.user.not-exist": "此电子邮件不存在。",
|
||||
"Auth.form.error.code.provide": "提供代码的代码不正确。",
|
||||
"Auth.form.error.password.matching": "密码不匹配。",
|
||||
"Auth.form.error.params.provide": "提供错误的参数。",
|
||||
"Auth.form.error.username.taken": "用户名已被使用",
|
||||
"Auth.form.error.email.taken": "邮箱已被使用",
|
||||
|
||||
"Auth.link.forgot-password": "忘记密码了吗?",
|
||||
"Auth.link.ready": "准备好登陆?",
|
||||
|
||||
"BoundRoute.title": "绑定路由到",
|
||||
|
||||
"components.Input.error.password.noMatch": "密码不匹配",
|
||||
|
||||
"Controller.input.label": "{label} ",
|
||||
"Controller.selectAll": "选择全部",
|
||||
|
||||
"EditForm.inputSelect.label.role": "认证用户的默认角色",
|
||||
"EditForm.inputSelect.description.role": "新验证身份的用户将被赋予所选角色。",
|
||||
"EditForm.inputSelect.subscriptions.label": "管理订阅配额",
|
||||
"EditForm.inputSelect.subscriptions.description": "限制每个每小时IP的订阅数。",
|
||||
"EditForm.inputSelect.durations.label": "持续时间",
|
||||
"EditForm.inputSelect.durations.description": "用户无法订阅的时间段。",
|
||||
|
||||
"EditForm.inputToggle.label.email": "每个电子邮件地址一个帐户",
|
||||
"EditForm.inputToggle.label.sign-up": "启用注册",
|
||||
"EditForm.inputToggle.description.email": "不允许用户使用不同的认证提供者(绑定的相同的电子邮件地址)来创建多个帐户。",
|
||||
"EditForm.inputToggle.description.sign-up": "当禁用(OFF)时,注册过程将被禁止。任何人无论使用任何的供应商都不可以订阅。",
|
||||
|
||||
"EditPage.cancel": "取消",
|
||||
"EditPage.submit": "保存",
|
||||
"EditPage.form.roles": "角色详情",
|
||||
"EditPage.form.roles.label.description": "描述",
|
||||
"EditPage.form.roles.label.name": "名称",
|
||||
"EditPage.form.roles.label.users": "与此角色相关联的用户数: ({number})",
|
||||
"EditPage.form.roles.name.error": "此值是必需的。",
|
||||
"EditPage.header.title": "{name} ",
|
||||
"EditPage.header.title.create": "创建一个新角色",
|
||||
"EditPage.header.description": "{description} ",
|
||||
"EditPage.header.description.create": " ",
|
||||
|
||||
"EditPage.notification.permissions.error": "获取权限(permission)时出错",
|
||||
"EditPage.notification.policies.error": "获取鉴权策略(policies)时出错",
|
||||
"EditPage.notification.role.error": "获取角色时出错",
|
||||
|
||||
"HeaderNav.link.advancedSettings": "高级设置",
|
||||
"HeaderNav.link.emailTemplates": "电子邮件模板",
|
||||
"HeaderNav.link.providers": "提供者",
|
||||
"HeaderNav.link.roles": "角色和权限",
|
||||
|
||||
"HomePage.header.title": "角色和权限",
|
||||
"HomePage.header.description": "定义用户的角色和权限。",
|
||||
|
||||
"InputSearch.placeholder": "搜索用户",
|
||||
|
||||
"List.button.roles": "添加新角色",
|
||||
"List.button.providers": "添加新供应商",
|
||||
|
||||
"List.title.emailTemplates.singular": "{number} 电子邮件模板是可用的",
|
||||
"List.title.emailTemplates.plural": "{number} 电子邮件模板是可用的",
|
||||
|
||||
"List.title.providers.disabled.singular": "{number} 被禁用",
|
||||
"List.title.providers.disabled.plural": "{number} 被禁用",
|
||||
"List.title.providers.enabled.singular": "{number} 个供应商被启用, ",
|
||||
"List.title.providers.enabled.plural": "{number} 个供应商被启用, ",
|
||||
|
||||
"List.title.roles.singular": "{number} 个角色可用",
|
||||
"List.title.roles.plural": "{number} 角色可用",
|
||||
|
||||
"notification.error.delete": "删除数据时出错",
|
||||
"notification.error.fetch": "获取数据时出错",
|
||||
"notification.error.fetchUser": "获取用户时出错",
|
||||
"notification.info.emailSent": "电子邮件已发送",
|
||||
"notification.success.delete": "该项已被删除",
|
||||
"notification.success.submit": "设置已被更新",
|
||||
|
||||
"plugin.description.short": "使用基于JWT的完整身份验证过程保护API",
|
||||
"plugin.description.long": "使用基于JWT的完整身份验证过程来保护API。这个插件还有一个ACL策略,允许你管理用户组之间的权限。",
|
||||
|
||||
"Plugin.permissions.application.description": "定义所有项目的允许操作。",
|
||||
"Plugin.permissions.plugins.description": "定义 {name} 插件所有允许的操作。",
|
||||
|
||||
"Plugins.header.title": "权限",
|
||||
"Plugins.header.description": "下面只列出路由绑定的操作。",
|
||||
|
||||
"Policies.InputSelect.empty": "没有",
|
||||
"Policies.InputSelect.label": "允许执行以下操作:",
|
||||
"Policies.header.hint": "选择应用程序或插件的操作,然后点击COG图标显示绑定的路由",
|
||||
"Policies.header.title": "高级设置",
|
||||
|
||||
"Email.template.validation_email": "电子邮件地址验证",
|
||||
"Email.template.reset_password": "重置密码",
|
||||
"Email.template.success_register": "注册成功",
|
||||
|
||||
"Auth.advanced.allow_register": "",
|
||||
|
||||
"PopUpForm.button.cancel": "取消",
|
||||
"PopUpForm.button.save": "保存",
|
||||
"PopUpForm.header.add.providers": "增加新的供应商(Provider)",
|
||||
"PopUpForm.header.edit.email-templates": "编辑电子邮件模版",
|
||||
"PopUpForm.header.edit.providers": "编译 {provider} 供应商",
|
||||
"PopUpForm.inputSelect.providers.label": "选择供应商",
|
||||
"PopUpForm.Email.options.from.name.label": "Shipper name",
|
||||
"PopUpForm.Email.options.from.email.label": "Shipper email",
|
||||
"PopUpForm.Email.options.response_email.label": "Response email",
|
||||
"PopUpForm.Email.options.object.label": "主题",
|
||||
"PopUpForm.Email.options.message.label": "消息",
|
||||
"PopUpForm.Email.validation_email.options.object.placeholder": "请确认您的电子邮件地址 %APP_NAME%",
|
||||
"PopUpForm.Email.reset_password.options.object.placeholder": "请确认您的电子邮件地址 %APP_NAME%",
|
||||
"PopUpForm.Email.success_register.options.object.placeholder": "请确认您的电子邮件地址 %APP_NAME%",
|
||||
"PopUpForm.Email.validation_email.options.message.placeholder": "<p>请点击此链接验证您的帐户</p>",
|
||||
"PopUpForm.Email.reset_password.options.message.placeholder": "<p>请点击此链接验证您的帐户</p>",
|
||||
"PopUpForm.Email.success_register.options.message.placeholder": "<p>请点击此链接验证您的帐户</p>",
|
||||
"PopUpForm.Email.options.from.email.placeholder": "johndoe@gmail.com",
|
||||
"PopUpForm.Email.options.response_email.placeholder": "johndoe@gmail.com",
|
||||
"PopUpForm.Email.options.from.name.placeholder": "John Doe",
|
||||
"PopUpForm.Providers.enabled.label": "启用",
|
||||
"PopUpForm.Providers.enabled.description": "如果禁用,用户将无法使用此供应商。",
|
||||
"PopUpForm.Providers.key.label": "Client ID",
|
||||
"PopUpForm.Providers.key.placeholder": "TEXT",
|
||||
"PopUpForm.Providers.secret.label": "Client Secret",
|
||||
"PopUpForm.Providers.secret.placeholder": "TEXT",
|
||||
"PopUpForm.Providers.redirectURL.front-end.label": "重定向URL",
|
||||
|
||||
|
||||
|
||||
"PopUpForm.Providers.facebook.providerConfig.redirectURL": "Facebook应用中配置的重定向URL",
|
||||
"PopUpForm.Providers.google.providerConfig.redirectURL": "Google应用中配置的重定向URL",
|
||||
"PopUpForm.Providers.github.providerConfig.redirectURL": "GitHub应用中配置的重定向URL",
|
||||
"PopUpForm.Providers.linkedin2.providerConfig.redirectURL": "Linkedin应用中配置的重定向URL",
|
||||
"PopUpForm.Providers.twitter.providerConfig.redirectURL": "Twitter应用中配置的重定向URL",
|
||||
|
||||
"PopUpForm.Providers.callback.placeholder": "TEXT",
|
||||
"PopUpForm.Email.email_templates.inputDescription": "如果你不确定如何使用变量, {link}",
|
||||
"PopUpForm.Email.link.documentation": "看看我们的文档。"
|
||||
}
|
||||
@ -124,7 +124,5 @@ module.exports = async cb => {
|
||||
await pluginStore.set({key: 'advanced', value});
|
||||
}
|
||||
|
||||
strapi.plugins['users-permissions'].services.userspermissions.syncSchema(() => {
|
||||
strapi.plugins['users-permissions'].services.userspermissions.initialize(cb);
|
||||
});
|
||||
strapi.plugins['users-permissions'].services.userspermissions.initialize(cb);
|
||||
};
|
||||
|
||||
@ -4,13 +4,15 @@ module.exports = {
|
||||
find: async function (params = {}, populate) {
|
||||
const records = await this.query(function(qb) {
|
||||
_.forEach(params.where, (where, key) => {
|
||||
qb.where(key, where[0].symbol, where[0].value);
|
||||
if (_.isArray(where.value)) {
|
||||
for (const value in where.value) {
|
||||
qb[value ? 'where' : 'orWhere'](key, where.symbol, where.value[value])
|
||||
}
|
||||
} else {
|
||||
qb.where(key, where.symbol, where.value);
|
||||
}
|
||||
});
|
||||
|
||||
if (params.sort) {
|
||||
qb.orderByRaw(params.sort);
|
||||
}
|
||||
|
||||
if (params.start) {
|
||||
qb.offset(params.start);
|
||||
}
|
||||
@ -18,9 +20,12 @@ module.exports = {
|
||||
if (params.limit) {
|
||||
qb.limit(params.limit);
|
||||
}
|
||||
}).fetchAll({
|
||||
})
|
||||
.orderBy(params.sort)
|
||||
.fetchAll({
|
||||
withRelated: populate || _.keys(_.groupBy(_.reject(this.associations, { autoPopulate: false }), 'alias'))
|
||||
});
|
||||
})
|
||||
|
||||
|
||||
return records ? records.toJSON() : records;
|
||||
},
|
||||
@ -108,6 +113,14 @@ module.exports = {
|
||||
.destroy();
|
||||
},
|
||||
|
||||
deleteMany: async function (params) {
|
||||
return await this
|
||||
.query(qb => {
|
||||
qb.whereIn(this.primaryKey, params[this.primaryKey] || params.id);
|
||||
})
|
||||
.destroy();
|
||||
},
|
||||
|
||||
search: async function (params) {
|
||||
return this
|
||||
.query(function(qb) {
|
||||
|
||||
@ -84,6 +84,16 @@ module.exports = {
|
||||
});
|
||||
},
|
||||
|
||||
deleteMany: async function (params) {
|
||||
// Delete entry.
|
||||
return this
|
||||
.remove({
|
||||
[this.primaryKey]: {
|
||||
$in: params[this.primaryKey] || params.id
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
search: async function (params) {
|
||||
const re = new RegExp(params.id);
|
||||
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "strapi-plugin-users-permissions",
|
||||
"version": "3.0.0-alpha.12",
|
||||
"version": "3.0.0-alpha.12.1.3",
|
||||
"description": "Protect your API with a full-authentication process based on JWT",
|
||||
"strapi": {
|
||||
"name": "Roles & Permissions",
|
||||
@ -31,7 +31,7 @@
|
||||
"uuid": "^3.1.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"strapi-helper-plugin": "3.0.0-alpha.12"
|
||||
"strapi-helper-plugin": "3.0.0-alpha.12.1.3"
|
||||
},
|
||||
"author": {
|
||||
"name": "Strapi team",
|
||||
@ -54,4 +54,4 @@
|
||||
"npm": ">= 5.0.0"
|
||||
},
|
||||
"license": "MIT"
|
||||
}
|
||||
}
|
||||
@ -174,7 +174,7 @@ module.exports = {
|
||||
},
|
||||
|
||||
getRoles: async () => {
|
||||
const roles = await strapi.query('role', 'users-permissions').find({ sort: 'name ASC' }, []);
|
||||
const roles = await strapi.query('role', 'users-permissions').find({ sort: '-name' }, []);
|
||||
|
||||
for (let i = 0; i < roles.length; ++i) {
|
||||
roles[i].id = roles[i].id || roles[i]._id;
|
||||
@ -186,11 +186,11 @@ module.exports = {
|
||||
|
||||
getRoutes: async () => {
|
||||
const routes = Object.keys(strapi.api || {}).reduce((acc, current) => {
|
||||
return acc.concat(strapi.api[current].config.routes);
|
||||
return acc.concat(_.get(strapi.api[current].config, 'routes', []));
|
||||
}, []);
|
||||
|
||||
const pluginsRoutes = Object.keys(strapi.plugins || {}).reduce((acc, current) => {
|
||||
acc[current] = strapi.plugins[current].config.routes;
|
||||
acc[current] = _.get(strapi.plugins[current].config, 'routes', []);
|
||||
|
||||
return acc;
|
||||
}, []);
|
||||
@ -275,16 +275,43 @@ module.exports = {
|
||||
.addPermission(Object.assign(action, { role: role.id || role._id }))
|
||||
)
|
||||
)
|
||||
),
|
||||
Promise.all(toRemove.map(action => strapi.query('permission', 'users-permissions').removePermission(action)))
|
||||
).concat([
|
||||
Promise.all(toRemove.map(action => strapi.query('permission', 'users-permissions').removePermission(action)))
|
||||
])
|
||||
);
|
||||
|
||||
this.writeActions(currentActions);
|
||||
return this.writeActions(currentActions, cb);
|
||||
}
|
||||
|
||||
if (cb) {
|
||||
cb();
|
||||
}
|
||||
cb();
|
||||
},
|
||||
|
||||
removeDuplicate: async function () {
|
||||
const primaryKey = strapi.query('permission', 'users-permissions').primaryKey;
|
||||
|
||||
// Retrieve permissions by creation date (ID or ObjectID).
|
||||
const permissions = await strapi.query('permission', 'users-permissions').find({
|
||||
sort: `${primaryKey}`
|
||||
});
|
||||
|
||||
const value = permissions.reduce((acc, permission) => {
|
||||
const index = acc.toKeep.findIndex(element => element === `${permission.type}.controllers.${permission.controller}.${permission.action}`);
|
||||
|
||||
if (index === -1) {
|
||||
acc.toKeep.push(`${permission.type}.controllers.${permission.controller}.${permission.action}`);
|
||||
} else {
|
||||
acc.toRemove.push(permission[primaryKey]);
|
||||
}
|
||||
|
||||
return acc;
|
||||
}, {
|
||||
toKeep: [],
|
||||
toRemove: []
|
||||
});
|
||||
|
||||
return strapi.query('permission', 'users-permissions').deleteMany({
|
||||
[primaryKey]: value.toRemove
|
||||
});
|
||||
},
|
||||
|
||||
initialize: async function (cb) {
|
||||
@ -292,6 +319,7 @@ module.exports = {
|
||||
|
||||
// It's has been already initialized.
|
||||
if (roles > 0) {
|
||||
await this.removeDuplicate();
|
||||
return await this.updatePermissions(cb);
|
||||
}
|
||||
|
||||
@ -384,196 +412,25 @@ module.exports = {
|
||||
});
|
||||
},
|
||||
|
||||
writeActions: (data) => {
|
||||
writeActions: (data, cb) => {
|
||||
const actionsPath = path.join(strapi.config.appPath, 'plugins', 'users-permissions', 'config', 'actions.json');
|
||||
|
||||
try {
|
||||
// Stop auto reload.
|
||||
strapi.reload.isReloading = false;
|
||||
// Disable auto-reload.
|
||||
strapi.reload.isWatching = false;
|
||||
// Rewrite actions.json file.
|
||||
fs.writeFileSync(actionsPath, JSON.stringify({ actions: data }), 'utf8');
|
||||
// Set value to AST to avoid restart.
|
||||
_.set(strapi.plugins['users-permissions'], 'config.actions', data);
|
||||
// Restart to watch files.
|
||||
strapi.reload.isReloading = true;
|
||||
// Disable auto-reload.
|
||||
strapi.reload.isWatching = true;
|
||||
|
||||
cb();
|
||||
} catch(err) {
|
||||
strapi.log.error(err);
|
||||
}
|
||||
},
|
||||
|
||||
syncSchema: async (cb) => {
|
||||
if (strapi.plugins['users-permissions'].models.user.orm !== 'bookshelf') {
|
||||
return cb();
|
||||
}
|
||||
|
||||
// Extract necessary information from plugin's models.
|
||||
const {
|
||||
user: { collectionName: userTableName, connection: userConnection, client: userClient },
|
||||
role: { collectionName: roleTableName, connection: roleConnection, client: roleClient },
|
||||
permission: { collectionName: permissionTableName, connection: permissionConnection, client: permissionClient }
|
||||
} = strapi.plugins['users-permissions'].models;
|
||||
|
||||
const details = {
|
||||
user: {
|
||||
tableName: userTableName,
|
||||
connection: userConnection,
|
||||
client: userClient
|
||||
},
|
||||
role: {
|
||||
tableName: roleTableName,
|
||||
connection: roleConnection,
|
||||
client: roleClient
|
||||
},
|
||||
permission: {
|
||||
tableName: permissionTableName,
|
||||
connection: permissionConnection,
|
||||
client: permissionClient
|
||||
}
|
||||
};
|
||||
|
||||
// Check if the tables are existing.
|
||||
const hasTables = await Promise.all(Object.keys(details).map(name =>
|
||||
strapi.connections[details[name].connection].schema.hasTable(details[name].tableName)
|
||||
));
|
||||
|
||||
const missingTables = [];
|
||||
const tablesToCreate = [];
|
||||
|
||||
for (let index = 0; index < hasTables.length; ++index) {
|
||||
const hasTable = hasTables[index];
|
||||
const currentModel = Object.keys(details)[index];
|
||||
const quote = details[currentModel].client === 'pg' ? '"' : '`';
|
||||
|
||||
if (!hasTable) {
|
||||
missingTables.push(`
|
||||
⚠️ TABLE \`${details[currentModel].tableName}\` DOESN'T EXIST`);
|
||||
|
||||
switch (currentModel) {
|
||||
case 'user':
|
||||
tablesToCreate.push(`
|
||||
|
||||
CREATE TABLE ${quote}${details[currentModel].tableName}${quote} (
|
||||
id ${details[currentModel].client === 'pg' ? 'SERIAL' : 'INT AUTO_INCREMENT'} NOT NULL PRIMARY KEY,
|
||||
username text,
|
||||
email text,
|
||||
provider text,
|
||||
role ${details[currentModel].client === 'pg' ? 'integer' : 'int'},
|
||||
${quote}resetPasswordToken${quote} text,
|
||||
password text,
|
||||
updated_at ${details[currentModel].client === 'pg' ? 'timestamp with time zone' : 'timestamp DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP'},
|
||||
created_at ${details[currentModel].client === 'pg' ? 'timestamp with time zone' : 'timestamp DEFAULT CURRENT_TIMESTAMP'}
|
||||
);`);
|
||||
break;
|
||||
case 'role':
|
||||
tablesToCreate.push(`
|
||||
|
||||
CREATE TABLE ${quote}${details[currentModel].tableName}${quote} (
|
||||
id ${details[currentModel].client === 'pg' ? 'SERIAL' : 'INT AUTO_INCREMENT'} NOT NULL PRIMARY KEY,
|
||||
name text,
|
||||
description text,
|
||||
type text
|
||||
);`);
|
||||
break;
|
||||
case 'permission':
|
||||
tablesToCreate.push(`
|
||||
|
||||
CREATE TABLE ${quote}${details[currentModel].tableName}${quote} (
|
||||
id ${details[currentModel].client === 'pg' ? 'SERIAL' : 'INT AUTO_INCREMENT'} NOT NULL PRIMARY KEY,
|
||||
role ${details[currentModel].client === 'pg' ? 'integer' : 'int'},
|
||||
type text,
|
||||
controller text,
|
||||
action text,
|
||||
enabled boolean,
|
||||
policy text
|
||||
);`);
|
||||
break;
|
||||
default:
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!_.isEmpty(tablesToCreate)) {
|
||||
tablesToCreate.unshift(`
|
||||
|
||||
1️⃣ EXECUTE THE FOLLOWING SQL QUERY`);
|
||||
|
||||
tablesToCreate.push(`
|
||||
|
||||
2️⃣ RESTART YOUR SERVER`);
|
||||
strapi.log.warn(missingTables.concat(tablesToCreate).join(''));
|
||||
|
||||
// Stop the server.
|
||||
strapi.stop();
|
||||
}
|
||||
|
||||
const missingColumns = [];
|
||||
const tablesToAlter = [];
|
||||
|
||||
for (let index = 0; index < hasTables.length; ++index) {
|
||||
const currentModel = Object.keys(details)[index];
|
||||
const quote = details[currentModel].client === 'pg' ? '"' : '`';
|
||||
const attributes = {
|
||||
id: {
|
||||
type: details[currentModel].client === 'pg' ? 'integer' : 'int'
|
||||
},
|
||||
..._.cloneDeep(strapi.plugins['users-permissions'].models[currentModel].attributes)
|
||||
};
|
||||
|
||||
// Add created_at and updated_at attributes for the model User.
|
||||
if (currentModel === 'user') {
|
||||
Object.assign(attributes, {
|
||||
created_at: {
|
||||
type: details[currentModel].client === 'pg' ? 'timestamp with time zone' : 'timestamp'
|
||||
},
|
||||
updated_at: {
|
||||
type: details[currentModel].client === 'pg' ? 'timestamp with time zone' : 'timestamp'
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
const columns = Object.keys(attributes);
|
||||
|
||||
// Check if there are the required attributes.
|
||||
const hasColumns = await Promise.all(columns.map(attribute =>
|
||||
strapi.connections[details[currentModel].connection].schema.hasColumn(details[currentModel].tableName, attribute)
|
||||
));
|
||||
|
||||
hasColumns.forEach((hasColumn, index) => {
|
||||
const currentColumn = columns[index];
|
||||
const attribute = attributes[currentColumn];
|
||||
|
||||
if (!hasColumn && !attribute.collection) {
|
||||
const currentType = attribute.model ? 'integer' : attribute.type;
|
||||
const type = currentType === 'string' ? 'text' : currentType;
|
||||
|
||||
missingColumns.push(`
|
||||
⚠️ TABLE \`${details[currentModel].tableName}\` HAS MISSING COLUMNS`);
|
||||
|
||||
tablesToAlter.push(`
|
||||
|
||||
ALTER TABLE ${quote}${details[currentModel].tableName}${quote} ADD ${details[currentModel].client === 'pg' ? `${quote}${currentColumn}${quote}` : `${currentColumn}`} ${type};`);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
if (!_.isEmpty(tablesToAlter)) {
|
||||
tablesToAlter.unshift(`
|
||||
|
||||
1️⃣ EXECUTE THE FOLLOWING SQL QUERIES`);
|
||||
|
||||
tablesToAlter.push(`
|
||||
|
||||
2️⃣ RESTART YOUR SERVER`);
|
||||
strapi.log.warn(missingColumns.concat(tablesToAlter).join(''));
|
||||
|
||||
// Stop the server.
|
||||
return strapi.stop();
|
||||
}
|
||||
|
||||
cb();
|
||||
},
|
||||
|
||||
template: (layout, data) => {
|
||||
const compiledObject = _.template(layout);
|
||||
return compiledObject(data);
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "strapi-redis",
|
||||
"version": "3.0.0-alpha.12",
|
||||
"version": "3.0.0-alpha.12.1.3",
|
||||
"description": "Redis hook for the Strapi framework",
|
||||
"homepage": "http://strapi.io",
|
||||
"keywords": [
|
||||
@ -18,7 +18,7 @@
|
||||
"ioredis": "^3.1.2",
|
||||
"lodash": "^4.17.4",
|
||||
"stack-trace": "0.0.10",
|
||||
"strapi-utils": "3.0.0-alpha.12"
|
||||
"strapi-utils": "3.0.0-alpha.12.1.3"
|
||||
},
|
||||
"strapi": {
|
||||
"isHook": true
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "strapi-upload-aws-s3",
|
||||
"version": "3.0.0-alpha.12",
|
||||
"version": "3.0.0-alpha.12.1.3",
|
||||
"description": "AWS S3 provider for strapi upload",
|
||||
"homepage": "http://strapi.io",
|
||||
"keywords": [
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "strapi-upload-cloudinary",
|
||||
"version": "3.0.0-alpha.12",
|
||||
"version": "3.0.0-alpha.12.1.3",
|
||||
"description": "Cloudinary provider for strapi upload",
|
||||
"homepage": "http://strapi.io",
|
||||
"keywords": [
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "strapi-upload-local",
|
||||
"version": "3.0.0-alpha.12",
|
||||
"version": "3.0.0-alpha.12.1.3",
|
||||
"description": "Local provider for strapi upload",
|
||||
"homepage": "http://strapi.io",
|
||||
"keywords": [
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "strapi-upload-rackspace",
|
||||
"version": "3.0.0-alpha.12",
|
||||
"version": "3.0.0-alpha.12.1.3",
|
||||
"description": "Rackspace provider for strapi upload",
|
||||
"main": "./lib",
|
||||
"scripts": {
|
||||
|
||||
@ -104,7 +104,7 @@ module.exports = {
|
||||
// We have to find if they are a model linked to this key
|
||||
_.forIn(allModels, model => {
|
||||
_.forIn(model.attributes, attribute => {
|
||||
if (attribute.hasOwnProperty('via') && attribute.via === key) {
|
||||
if (attribute.hasOwnProperty('via') && attribute.via === key && attribute.model === currentModelName) {
|
||||
if (attribute.hasOwnProperty('collection')) {
|
||||
types.other = 'collection';
|
||||
|
||||
@ -141,30 +141,16 @@ module.exports = {
|
||||
types.current = 'modelD';
|
||||
|
||||
// We have to find if they are a model linked to this key
|
||||
_.forIn(_.omit(models, currentModelName || ''), model => {
|
||||
Object.keys(model.attributes)
|
||||
.filter(key => key === association.via)
|
||||
.forEach(attr => {
|
||||
const attribute = model.attributes[attr];
|
||||
const model = models[association.model]
|
||||
const attribute = model.attributes[association.via];
|
||||
|
||||
if (attribute.hasOwnProperty('via') && attribute.via === key && attribute.hasOwnProperty('collection') && attribute.collection !== '*') {
|
||||
types.other = 'collection';
|
||||
|
||||
// Break loop
|
||||
return false;
|
||||
} else if (attribute.hasOwnProperty('model') && attribute.model !== '*') {
|
||||
types.other = 'model';
|
||||
|
||||
// Break loop
|
||||
return false;
|
||||
} else if (attribute.hasOwnProperty('collection') || attribute.hasOwnProperty('model')) {
|
||||
types.other = 'morphTo';
|
||||
|
||||
// Break loop
|
||||
return false;
|
||||
}
|
||||
});
|
||||
});
|
||||
if (attribute.hasOwnProperty('via') && attribute.via === key && attribute.hasOwnProperty('collection') && attribute.collection !== '*') {
|
||||
types.other = 'collection';
|
||||
} else if (attribute.hasOwnProperty('model') && attribute.model !== '*') {
|
||||
types.other = 'model';
|
||||
} else if (attribute.hasOwnProperty('collection') || attribute.hasOwnProperty('model')) {
|
||||
types.other = 'morphTo';
|
||||
}
|
||||
} else if (association.hasOwnProperty('model')) {
|
||||
types.current = 'model';
|
||||
|
||||
@ -455,7 +441,7 @@ module.exports = {
|
||||
if (_.includes(['_start', '_limit'], key)) {
|
||||
result = convertor(value, key);
|
||||
} else if (key === '_sort') {
|
||||
const [attr, order] = value.split(':');
|
||||
const [attr, order = 'ASC'] = value.split(':');
|
||||
result = convertor(order, key, attr);
|
||||
} else {
|
||||
const suffix = key.split('_');
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "strapi-utils",
|
||||
"version": "3.0.0-alpha.12",
|
||||
"version": "3.0.0-alpha.12.1.3",
|
||||
"description": "Shared utilities for the Strapi packages",
|
||||
"homepage": "http://strapi.io",
|
||||
"keywords": [
|
||||
|
||||
@ -203,8 +203,8 @@ class Strapi extends EventEmitter {
|
||||
// Usage.
|
||||
await utils.usage.call(this);
|
||||
|
||||
// Init core store manager
|
||||
await store.pre.call(this);
|
||||
// Init core store
|
||||
await store.call(this);
|
||||
|
||||
// Initialize hooks and middlewares.
|
||||
await Promise.all([
|
||||
@ -212,9 +212,6 @@ class Strapi extends EventEmitter {
|
||||
initializeHooks.call(this)
|
||||
]);
|
||||
|
||||
// Core store post middleware and hooks init validation.
|
||||
await store.post.call(this);
|
||||
|
||||
// Harmonize plugins configuration.
|
||||
await plugins.call(this);
|
||||
}
|
||||
|
||||
@ -1,179 +1,138 @@
|
||||
'use strict';
|
||||
|
||||
module.exports = {
|
||||
pre: function () {
|
||||
return new Promise((resolve) => {
|
||||
this.models['core_store'] = {
|
||||
connection: 'default',
|
||||
info: {
|
||||
name: 'core_store',
|
||||
description: ''
|
||||
module.exports = function () {
|
||||
return new Promise((resolve) => {
|
||||
this.models['core_store'] = {
|
||||
connection: 'default',
|
||||
info: {
|
||||
name: 'core_store',
|
||||
description: ''
|
||||
},
|
||||
attributes: {
|
||||
key: {
|
||||
type: 'string'
|
||||
},
|
||||
attributes: {
|
||||
key: {
|
||||
type: 'string'
|
||||
},
|
||||
value: {
|
||||
type: 'string'
|
||||
},
|
||||
type: {
|
||||
type: 'string'
|
||||
},
|
||||
environment: {
|
||||
type: 'string'
|
||||
},
|
||||
tag: {
|
||||
type: 'string'
|
||||
value: {
|
||||
type: 'text'
|
||||
},
|
||||
type: {
|
||||
type: 'string'
|
||||
},
|
||||
environment: {
|
||||
type: 'string'
|
||||
},
|
||||
tag: {
|
||||
type: 'string'
|
||||
}
|
||||
},
|
||||
globalId: 'StrapiConfigs',
|
||||
collectionName: 'core_store'
|
||||
};
|
||||
|
||||
this.store = (source = {}) => {
|
||||
const get = async (params = {}) => {
|
||||
Object.assign(source, params);
|
||||
|
||||
const {
|
||||
key,
|
||||
environment = strapi.config.environment,
|
||||
type = 'core',
|
||||
name = '',
|
||||
tag = ''
|
||||
} = source;
|
||||
|
||||
const prefix = `${type}${name ? `_${name}` : ''}`;
|
||||
|
||||
const findAction = strapi.models['core_store'].orm === 'mongoose' ? 'findOne' : 'forge';
|
||||
|
||||
const where = {
|
||||
key: `${prefix}_${key}`,
|
||||
environment,
|
||||
tag
|
||||
};
|
||||
|
||||
const data = strapi.models['core_store'].orm === 'mongoose'
|
||||
? await strapi.models['core_store'].findOne(where)
|
||||
: await strapi.models['core_store'].forge(where).fetch().then(config => {
|
||||
if (config) {
|
||||
return config.toJSON();
|
||||
}
|
||||
},
|
||||
globalId: 'StrapiConfigs',
|
||||
collectionName: 'core_store'
|
||||
});
|
||||
|
||||
if (!data) {
|
||||
return null;
|
||||
}
|
||||
|
||||
if (data.type === 'object' || data.type === 'array' || data.type === 'boolean') {
|
||||
try {
|
||||
return JSON.parse(data.value);
|
||||
} catch (err) {
|
||||
return new Date(data.value);
|
||||
}
|
||||
} else if (data.type === 'number') {
|
||||
return parseFloat(data.value);
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
};
|
||||
|
||||
this.store = (source = {}) => {
|
||||
const get = async (params = {}) => {
|
||||
Object.assign(source, params);
|
||||
const set = async (params = {}) => {
|
||||
Object.assign(source, params);
|
||||
|
||||
const {
|
||||
key,
|
||||
environment = strapi.config.environment,
|
||||
type = 'core',
|
||||
name = '',
|
||||
tag = ''
|
||||
} = source;
|
||||
const {
|
||||
key,
|
||||
value,
|
||||
environment = strapi.config.environment,
|
||||
type,
|
||||
name,
|
||||
tag = ''
|
||||
} = source;
|
||||
|
||||
const prefix = `${type}${name ? `_${name}` : ''}`;
|
||||
const prefix = `${type}${name ? `_${name}` : ''}`;
|
||||
|
||||
// NOTE: why don't we need this variable?
|
||||
// const findAction = strapi.models['core_store'].orm === 'mongoose' ? 'findOne' : 'forge';
|
||||
const where = {
|
||||
key: `${prefix}_${key}`,
|
||||
environment,
|
||||
tag
|
||||
};
|
||||
|
||||
const where = {
|
||||
key: `${prefix}_${key}`,
|
||||
environment,
|
||||
let data = strapi.models['core_store'].orm === 'mongoose'
|
||||
? await strapi.models['core_store'].findOne(where)
|
||||
: await strapi.models['core_store'].forge(where).fetch().then(config => {
|
||||
if (config) {
|
||||
return config.toJSON();
|
||||
}
|
||||
});
|
||||
|
||||
if (data) {
|
||||
Object.assign(data, {
|
||||
value: JSON.stringify(value) || value.toString(),
|
||||
type: (typeof value).toString()
|
||||
});
|
||||
|
||||
strapi.models['core_store'].orm === 'mongoose'
|
||||
? await strapi.models['core_store'].update({ _id: data._id }, data, { strict: false })
|
||||
: await strapi.models['core_store'].forge({ id: data.id }).save(data, { patch: true });
|
||||
} else {
|
||||
Object.assign(where, {
|
||||
value: JSON.stringify(value) || value.toString(),
|
||||
type: (typeof value).toString(),
|
||||
tag
|
||||
};
|
||||
|
||||
const data = strapi.models['core_store'].orm === 'mongoose'
|
||||
? await strapi.models['core_store'].findOne(where)
|
||||
: await strapi.models['core_store'].forge(where).fetch().then(config => {
|
||||
if (config) {
|
||||
return config.toJSON();
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
if (!data) {
|
||||
return null;
|
||||
}
|
||||
|
||||
if (data.type === 'object' || data.type === 'array' || data.type === 'boolean') {
|
||||
try {
|
||||
return JSON.parse(data.value);
|
||||
} catch (err) {
|
||||
return new Date(data.value);
|
||||
}
|
||||
} else if (data.type === 'number') {
|
||||
return parseFloat(data.value);
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
};
|
||||
|
||||
const set = async (params = {}) => {
|
||||
Object.assign(source, params);
|
||||
|
||||
const {
|
||||
key,
|
||||
value,
|
||||
environment = strapi.config.environment,
|
||||
type,
|
||||
name,
|
||||
tag = ''
|
||||
} = source;
|
||||
|
||||
const prefix = `${type}${name ? `_${name}` : ''}`;
|
||||
|
||||
const where = {
|
||||
key: `${prefix}_${key}`,
|
||||
environment,
|
||||
tag
|
||||
};
|
||||
|
||||
let data = strapi.models['core_store'].orm === 'mongoose'
|
||||
? await strapi.models['core_store'].findOne(where)
|
||||
: await strapi.models['core_store'].forge(where).fetch().then(config => {
|
||||
if (config) {
|
||||
return config.toJSON();
|
||||
}
|
||||
});
|
||||
|
||||
if (data) {
|
||||
Object.assign(data, {
|
||||
value: JSON.stringify(value) || value.toString(),
|
||||
type: (typeof value).toString()
|
||||
});
|
||||
|
||||
strapi.models['core_store'].orm === 'mongoose'
|
||||
? await strapi.models['core_store'].update({ _id: data._id }, data, { strict: false })
|
||||
: await strapi.models['core_store'].forge({ id: data.id }).save(data, { patch: true });
|
||||
} else {
|
||||
Object.assign(where, {
|
||||
value: JSON.stringify(value) || value.toString(),
|
||||
type: (typeof value).toString(),
|
||||
tag
|
||||
});
|
||||
|
||||
strapi.models['core_store'].orm === 'mongoose'
|
||||
? await strapi.models['core_store'].create(where)
|
||||
: await strapi.models['core_store'].forge().save(where);
|
||||
}
|
||||
};
|
||||
|
||||
return {
|
||||
get,
|
||||
set
|
||||
};
|
||||
strapi.models['core_store'].orm === 'mongoose'
|
||||
? await strapi.models['core_store'].create(where)
|
||||
: await strapi.models['core_store'].forge().save(where);
|
||||
}
|
||||
};
|
||||
|
||||
resolve();
|
||||
});
|
||||
},
|
||||
post: function () {
|
||||
return new Promise(async (resolve) => {
|
||||
const Model = this.models['core_store'];
|
||||
|
||||
if (Model.orm !== 'bookshelf') {
|
||||
return resolve();
|
||||
return {
|
||||
get,
|
||||
set
|
||||
}
|
||||
}
|
||||
|
||||
const hasTable = await this.connections[Model.connection].schema.hasTable(Model.tableName || Model.collectionName);
|
||||
|
||||
if (!hasTable) {
|
||||
const quote = Model.client === 'pg' ? '"' : '`';
|
||||
|
||||
this.log.warn(`
|
||||
⚠️ TABLE \`core_store\` DOESN'T EXIST
|
||||
|
||||
CREATE TABLE ${quote}${Model.tableName || Model.collectionName}${quote} (
|
||||
id ${Model.client === 'pg' ? 'SERIAL' : 'INT AUTO_INCREMENT'} NOT NULL PRIMARY KEY,
|
||||
${quote}key${quote} text,
|
||||
${quote}value${quote} text,
|
||||
environment text,
|
||||
type text,
|
||||
tag text
|
||||
);
|
||||
|
||||
ALTER TABLE ${quote}${Model.tableName || Model.collectionName}${quote} ADD COLUMN ${quote}parent${quote} integer, ADD FOREIGN KEY (${quote}parent${quote}) REFERENCES ${quote}${Model.tableName || Model.collectionName}${quote}(${quote}id${quote});
|
||||
|
||||
1️⃣ EXECUTE THE FOLLOWING SQL QUERY
|
||||
|
||||
2️⃣ RESTART YOUR SERVER
|
||||
`);
|
||||
|
||||
// Stop the server.
|
||||
return this.stop();
|
||||
}
|
||||
|
||||
resolve();
|
||||
});
|
||||
}
|
||||
resolve();
|
||||
});
|
||||
};
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "strapi",
|
||||
"version": "3.0.0-alpha.12",
|
||||
"version": "3.0.0-alpha.12.1.3",
|
||||
"description": "An open source solution to create and manage your own API. It provides a powerful dashboard and features to make your life easier.",
|
||||
"homepage": "http://strapi.io",
|
||||
"keywords": [
|
||||
@ -55,14 +55,14 @@
|
||||
"rimraf": "^2.6.2",
|
||||
"semver": "^5.4.1",
|
||||
"stack-trace": "0.0.10",
|
||||
"strapi-generate": "3.0.0-alpha.12",
|
||||
"strapi-generate-admin": "3.0.0-alpha.12",
|
||||
"strapi-generate-api": "3.0.0-alpha.12",
|
||||
"strapi-generate-new": "3.0.0-alpha.12",
|
||||
"strapi-generate-plugin": "3.0.0-alpha.12",
|
||||
"strapi-generate-policy": "3.0.0-alpha.12",
|
||||
"strapi-generate-service": "3.0.0-alpha.12",
|
||||
"strapi-utils": "3.0.0-alpha.12"
|
||||
"strapi-generate": "3.0.0-alpha.12.1.3",
|
||||
"strapi-generate-admin": "3.0.0-alpha.12.1.3",
|
||||
"strapi-generate-api": "3.0.0-alpha.12.1.3",
|
||||
"strapi-generate-new": "3.0.0-alpha.12.1.3",
|
||||
"strapi-generate-plugin": "3.0.0-alpha.12.1.3",
|
||||
"strapi-generate-policy": "3.0.0-alpha.12.1.3",
|
||||
"strapi-generate-service": "3.0.0-alpha.12.1.3",
|
||||
"strapi-utils": "3.0.0-alpha.12.1.3"
|
||||
},
|
||||
"author": {
|
||||
"email": "hi@strapi.io",
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user