init: Upload Code From Github

要提交的变更:
	修改:     README.md
	新文件:   README_zh-CN.md
	新文件:   assets/CHANGELOG.md
	新文件:   assets/Parsedown.php
	新文件:   assets/css/login.css
	新文件:   assets/css/manage.css
	新文件:   assets/defaultConfig.json
	新文件:   assets/defaultIconList.json
	新文件:   assets/html/favicon.ico
	新文件:   assets/html/login.html
	新文件:   assets/html/manage.html
	新文件:   assets/js/console.js
	新文件:   assets/js/manage.js
	新文件:   assets/opencc/composer.json
	新文件:   assets/opencc/composer.lock
	新文件:   assets/opencc/vendor/autoload.php
	新文件:   assets/opencc/vendor/bin/opencc
	新文件:   assets/opencc/vendor/composer/ClassLoader.php
	新文件:   assets/opencc/vendor/composer/InstalledVersions.php
	新文件:   assets/opencc/vendor/composer/LICENSE
	新文件:   assets/opencc/vendor/composer/autoload_classmap.php
	新文件:   assets/opencc/vendor/composer/autoload_files.php
	新文件:   assets/opencc/vendor/composer/autoload_namespaces.php
	新文件:   assets/opencc/vendor/composer/autoload_psr4.php
	新文件:   assets/opencc/vendor/composer/autoload_real.php
	新文件:   assets/opencc/vendor/composer/autoload_static.php
	新文件:   assets/opencc/vendor/composer/installed.json
	新文件:   assets/opencc/vendor/composer/installed.php
	新文件:   assets/opencc/vendor/composer/platform_check.php
	新文件:   assets/opencc/vendor/overtrue/php-opencc/.editorconfig
	新文件:   assets/opencc/vendor/overtrue/php-opencc/.github/FUNDING.yml
	新文件:   assets/opencc/vendor/overtrue/php-opencc/.github/workflows/test.yml
	新文件:   assets/opencc/vendor/overtrue/php-opencc/LICENSE
	新文件:   assets/opencc/vendor/overtrue/php-opencc/README.md
	新文件:   assets/opencc/vendor/overtrue/php-opencc/bin/build
	新文件:   assets/opencc/vendor/overtrue/php-opencc/bin/opencc
	新文件:   assets/opencc/vendor/overtrue/php-opencc/composer.json
	新文件:   assets/opencc/vendor/overtrue/php-opencc/data/dictionary/HKVariants.txt
	新文件:   assets/opencc/vendor/overtrue/php-opencc/data/dictionary/HKVariantsRevPhrases.txt
	新文件:   assets/opencc/vendor/overtrue/php-opencc/data/dictionary/JPShinjitaiCharacters.txt
	新文件:   assets/opencc/vendor/overtrue/php-opencc/data/dictionary/JPShinjitaiPhrases.txt
	新文件:   assets/opencc/vendor/overtrue/php-opencc/data/dictionary/JPVariants.txt
	新文件:   assets/opencc/vendor/overtrue/php-opencc/data/dictionary/README.md
	新文件:   assets/opencc/vendor/overtrue/php-opencc/data/dictionary/STCharacters.txt
	新文件:   assets/opencc/vendor/overtrue/php-opencc/data/dictionary/STPhrases.txt
	新文件:   assets/opencc/vendor/overtrue/php-opencc/data/dictionary/TSCharacters.txt
	新文件:   assets/opencc/vendor/overtrue/php-opencc/data/dictionary/TSPhrases.txt
	新文件:   assets/opencc/vendor/overtrue/php-opencc/data/dictionary/TWPhrasesIT.txt
	新文件:   assets/opencc/vendor/overtrue/php-opencc/data/dictionary/TWPhrasesName.txt
	新文件:   assets/opencc/vendor/overtrue/php-opencc/data/dictionary/TWPhrasesOther.txt
	新文件:   assets/opencc/vendor/overtrue/php-opencc/data/dictionary/TWVariants.txt
	新文件:   assets/opencc/vendor/overtrue/php-opencc/data/dictionary/TWVariantsRevPhrases.txt
	新文件:   assets/opencc/vendor/overtrue/php-opencc/data/parsed/HKVariants.php
	新文件:   assets/opencc/vendor/overtrue/php-opencc/data/parsed/HKVariantsRev.php
	新文件:   assets/opencc/vendor/overtrue/php-opencc/data/parsed/HKVariantsRevPhrases.php
	新文件:   assets/opencc/vendor/overtrue/php-opencc/data/parsed/JPShinjitaiCharacters.php
	新文件:   assets/opencc/vendor/overtrue/php-opencc/data/parsed/JPShinjitaiPhrases.php
	新文件:   assets/opencc/vendor/overtrue/php-opencc/data/parsed/JPVariants.php
	新文件:   assets/opencc/vendor/overtrue/php-opencc/data/parsed/JPVariantsRev.php
	新文件:   assets/opencc/vendor/overtrue/php-opencc/data/parsed/STCharacters.php
	新文件:   assets/opencc/vendor/overtrue/php-opencc/data/parsed/STPhrases.php
	新文件:   assets/opencc/vendor/overtrue/php-opencc/data/parsed/TSCharacters.php
	新文件:   assets/opencc/vendor/overtrue/php-opencc/data/parsed/TSPhrases.php
	新文件:   assets/opencc/vendor/overtrue/php-opencc/data/parsed/TWPhrases.php
	新文件:   assets/opencc/vendor/overtrue/php-opencc/data/parsed/TWPhrasesIT.php
	新文件:   assets/opencc/vendor/overtrue/php-opencc/data/parsed/TWPhrasesName.php
	新文件:   assets/opencc/vendor/overtrue/php-opencc/data/parsed/TWPhrasesOther.php
	新文件:   assets/opencc/vendor/overtrue/php-opencc/data/parsed/TWPhrasesRev.php
	新文件:   assets/opencc/vendor/overtrue/php-opencc/data/parsed/TWVariants.php
	新文件:   assets/opencc/vendor/overtrue/php-opencc/data/parsed/TWVariantsRev.php
	新文件:   assets/opencc/vendor/overtrue/php-opencc/data/parsed/TWVariantsRevPhrases.php
	新文件:   assets/opencc/vendor/overtrue/php-opencc/src/Console/BuildCommand.php
	新文件:   assets/opencc/vendor/overtrue/php-opencc/src/Console/ConvertCommand.php
	新文件:   assets/opencc/vendor/overtrue/php-opencc/src/Contracts/ConverterInterface.php
	新文件:   assets/opencc/vendor/overtrue/php-opencc/src/Converter.php
	新文件:   assets/opencc/vendor/overtrue/php-opencc/src/Dictionary.php
	新文件:   assets/opencc/vendor/overtrue/php-opencc/src/OpenCC.php
	新文件:   assets/opencc/vendor/overtrue/php-opencc/src/Strategy.php
	新文件:   assets/opencc/vendor/psr/container/.gitignore
	新文件:   assets/opencc/vendor/psr/container/LICENSE
	新文件:   assets/opencc/vendor/psr/container/README.md
	新文件:   assets/opencc/vendor/psr/container/composer.json
	新文件:   assets/opencc/vendor/psr/container/src/ContainerExceptionInterface.php
	新文件:   assets/opencc/vendor/psr/container/src/ContainerInterface.php
	新文件:   assets/opencc/vendor/psr/container/src/NotFoundExceptionInterface.php
	新文件:   assets/opencc/vendor/symfony/console/Application.php
	新文件:   assets/opencc/vendor/symfony/console/Attribute/AsCommand.php
	新文件:   assets/opencc/vendor/symfony/console/CHANGELOG.md
	新文件:   assets/opencc/vendor/symfony/console/CI/GithubActionReporter.php
	新文件:   assets/opencc/vendor/symfony/console/Color.php
	新文件:   assets/opencc/vendor/symfony/console/Command/Command.php
	新文件:   assets/opencc/vendor/symfony/console/Command/CompleteCommand.php
	新文件:   assets/opencc/vendor/symfony/console/Command/DumpCompletionCommand.php
	新文件:   assets/opencc/vendor/symfony/console/Command/HelpCommand.php
	新文件:   assets/opencc/vendor/symfony/console/Command/LazyCommand.php
	新文件:   assets/opencc/vendor/symfony/console/Command/ListCommand.php
	新文件:   assets/opencc/vendor/symfony/console/Command/LockableTrait.php
	新文件:   assets/opencc/vendor/symfony/console/Command/SignalableCommandInterface.php
	新文件:   assets/opencc/vendor/symfony/console/Command/TraceableCommand.php
	新文件:   assets/opencc/vendor/symfony/console/CommandLoader/CommandLoaderInterface.php
	新文件:   assets/opencc/vendor/symfony/console/CommandLoader/ContainerCommandLoader.php
	新文件:   assets/opencc/vendor/symfony/console/CommandLoader/FactoryCommandLoader.php
	新文件:   assets/opencc/vendor/symfony/console/Completion/CompletionInput.php
	新文件:   assets/opencc/vendor/symfony/console/Completion/CompletionSuggestions.php
	新文件:   assets/opencc/vendor/symfony/console/Completion/Output/BashCompletionOutput.php
	新文件:   assets/opencc/vendor/symfony/console/Completion/Output/CompletionOutputInterface.php
	新文件:   assets/opencc/vendor/symfony/console/Completion/Output/FishCompletionOutput.php
	新文件:   assets/opencc/vendor/symfony/console/Completion/Output/ZshCompletionOutput.php
	新文件:   assets/opencc/vendor/symfony/console/Completion/Suggestion.php
	新文件:   assets/opencc/vendor/symfony/console/ConsoleEvents.php
	新文件:   assets/opencc/vendor/symfony/console/Cursor.php
	新文件:   assets/opencc/vendor/symfony/console/DataCollector/CommandDataCollector.php
	新文件:   assets/opencc/vendor/symfony/console/Debug/CliRequest.php
	新文件:   assets/opencc/vendor/symfony/console/DependencyInjection/AddConsoleCommandPass.php
	新文件:   assets/opencc/vendor/symfony/console/Descriptor/ApplicationDescription.php
	新文件:   assets/opencc/vendor/symfony/console/Descriptor/Descriptor.php
	新文件:   assets/opencc/vendor/symfony/console/Descriptor/DescriptorInterface.php
	新文件:   assets/opencc/vendor/symfony/console/Descriptor/JsonDescriptor.php
	新文件:   assets/opencc/vendor/symfony/console/Descriptor/MarkdownDescriptor.php
	新文件:   assets/opencc/vendor/symfony/console/Descriptor/ReStructuredTextDescriptor.php
	新文件:   assets/opencc/vendor/symfony/console/Descriptor/TextDescriptor.php
	新文件:   assets/opencc/vendor/symfony/console/Descriptor/XmlDescriptor.php
	新文件:   assets/opencc/vendor/symfony/console/Event/ConsoleCommandEvent.php
	新文件:   assets/opencc/vendor/symfony/console/Event/ConsoleErrorEvent.php
	新文件:   assets/opencc/vendor/symfony/console/Event/ConsoleEvent.php
	新文件:   assets/opencc/vendor/symfony/console/Event/ConsoleSignalEvent.php
	新文件:   assets/opencc/vendor/symfony/console/Event/ConsoleTerminateEvent.php
	新文件:   assets/opencc/vendor/symfony/console/EventListener/ErrorListener.php
	新文件:   assets/opencc/vendor/symfony/console/Exception/CommandNotFoundException.php
	新文件:   assets/opencc/vendor/symfony/console/Exception/ExceptionInterface.php
	新文件:   assets/opencc/vendor/symfony/console/Exception/InvalidArgumentException.php
	新文件:   assets/opencc/vendor/symfony/console/Exception/InvalidOptionException.php
	新文件:   assets/opencc/vendor/symfony/console/Exception/LogicException.php
	新文件:   assets/opencc/vendor/symfony/console/Exception/MissingInputException.php
	新文件:   assets/opencc/vendor/symfony/console/Exception/NamespaceNotFoundException.php
	新文件:   assets/opencc/vendor/symfony/console/Exception/RunCommandFailedException.php
	新文件:   assets/opencc/vendor/symfony/console/Exception/RuntimeException.php
	新文件:   assets/opencc/vendor/symfony/console/Formatter/NullOutputFormatter.php
	新文件:   assets/opencc/vendor/symfony/console/Formatter/NullOutputFormatterStyle.php
	新文件:   assets/opencc/vendor/symfony/console/Formatter/OutputFormatter.php
	新文件:   assets/opencc/vendor/symfony/console/Formatter/OutputFormatterInterface.php
	新文件:   assets/opencc/vendor/symfony/console/Formatter/OutputFormatterStyle.php
	新文件:   assets/opencc/vendor/symfony/console/Formatter/OutputFormatterStyleInterface.php
	新文件:   assets/opencc/vendor/symfony/console/Formatter/OutputFormatterStyleStack.php
	新文件:   assets/opencc/vendor/symfony/console/Formatter/WrappableOutputFormatterInterface.php
	新文件:   assets/opencc/vendor/symfony/console/Helper/DebugFormatterHelper.php
	新文件:   assets/opencc/vendor/symfony/console/Helper/DescriptorHelper.php
	新文件:   assets/opencc/vendor/symfony/console/Helper/Dumper.php
	新文件:   assets/opencc/vendor/symfony/console/Helper/FormatterHelper.php
	新文件:   assets/opencc/vendor/symfony/console/Helper/Helper.php
	新文件:   assets/opencc/vendor/symfony/console/Helper/HelperInterface.php
	新文件:   assets/opencc/vendor/symfony/console/Helper/HelperSet.php
	新文件:   assets/opencc/vendor/symfony/console/Helper/InputAwareHelper.php
	新文件:   assets/opencc/vendor/symfony/console/Helper/OutputWrapper.php
	新文件:   assets/opencc/vendor/symfony/console/Helper/ProcessHelper.php
	新文件:   assets/opencc/vendor/symfony/console/Helper/ProgressBar.php
	新文件:   assets/opencc/vendor/symfony/console/Helper/ProgressIndicator.php
	新文件:   assets/opencc/vendor/symfony/console/Helper/QuestionHelper.php
	新文件:   assets/opencc/vendor/symfony/console/Helper/SymfonyQuestionHelper.php
	新文件:   assets/opencc/vendor/symfony/console/Helper/Table.php
	新文件:   assets/opencc/vendor/symfony/console/Helper/TableCell.php
	新文件:   assets/opencc/vendor/symfony/console/Helper/TableCellStyle.php
	新文件:   assets/opencc/vendor/symfony/console/Helper/TableRows.php
	新文件:   assets/opencc/vendor/symfony/console/Helper/TableSeparator.php
	新文件:   assets/opencc/vendor/symfony/console/Helper/TableStyle.php
	新文件:   assets/opencc/vendor/symfony/console/Input/ArgvInput.php
	新文件:   assets/opencc/vendor/symfony/console/Input/ArrayInput.php
	新文件:   assets/opencc/vendor/symfony/console/Input/Input.php
	新文件:   assets/opencc/vendor/symfony/console/Input/InputArgument.php
	新文件:   assets/opencc/vendor/symfony/console/Input/InputAwareInterface.php
	新文件:   assets/opencc/vendor/symfony/console/Input/InputDefinition.php
	新文件:   assets/opencc/vendor/symfony/console/Input/InputInterface.php
	新文件:   assets/opencc/vendor/symfony/console/Input/InputOption.php
	新文件:   assets/opencc/vendor/symfony/console/Input/StreamableInputInterface.php
	新文件:   assets/opencc/vendor/symfony/console/Input/StringInput.php
	新文件:   assets/opencc/vendor/symfony/console/LICENSE
	新文件:   assets/opencc/vendor/symfony/console/Logger/ConsoleLogger.php
	新文件:   assets/opencc/vendor/symfony/console/Messenger/RunCommandContext.php
	新文件:   assets/opencc/vendor/symfony/console/Messenger/RunCommandMessage.php
	新文件:   assets/opencc/vendor/symfony/console/Messenger/RunCommandMessageHandler.php
	新文件:   assets/opencc/vendor/symfony/console/Output/AnsiColorMode.php
	新文件:   assets/opencc/vendor/symfony/console/Output/BufferedOutput.php
	新文件:   assets/opencc/vendor/symfony/console/Output/ConsoleOutput.php
	新文件:   assets/opencc/vendor/symfony/console/Output/ConsoleOutputInterface.php
	新文件:   assets/opencc/vendor/symfony/console/Output/ConsoleSectionOutput.php
	新文件:   assets/opencc/vendor/symfony/console/Output/NullOutput.php
	新文件:   assets/opencc/vendor/symfony/console/Output/Output.php
	新文件:   assets/opencc/vendor/symfony/console/Output/OutputInterface.php
	新文件:   assets/opencc/vendor/symfony/console/Output/StreamOutput.php
	新文件:   assets/opencc/vendor/symfony/console/Output/TrimmedBufferOutput.php
	新文件:   assets/opencc/vendor/symfony/console/Question/ChoiceQuestion.php
	新文件:   assets/opencc/vendor/symfony/console/Question/ConfirmationQuestion.php
	新文件:   assets/opencc/vendor/symfony/console/Question/Question.php
	新文件:   assets/opencc/vendor/symfony/console/README.md
	新文件:   assets/opencc/vendor/symfony/console/Resources/bin/hiddeninput.exe
	新文件:   assets/opencc/vendor/symfony/console/Resources/completion.bash
	新文件:   assets/opencc/vendor/symfony/console/Resources/completion.fish
	新文件:   assets/opencc/vendor/symfony/console/Resources/completion.zsh
	新文件:   assets/opencc/vendor/symfony/console/SignalRegistry/SignalMap.php
	新文件:   assets/opencc/vendor/symfony/console/SignalRegistry/SignalRegistry.php
	新文件:   assets/opencc/vendor/symfony/console/SingleCommandApplication.php
	新文件:   assets/opencc/vendor/symfony/console/Style/OutputStyle.php
	新文件:   assets/opencc/vendor/symfony/console/Style/StyleInterface.php
	新文件:   assets/opencc/vendor/symfony/console/Style/SymfonyStyle.php
	新文件:   assets/opencc/vendor/symfony/console/Terminal.php
	新文件:   assets/opencc/vendor/symfony/console/Tester/ApplicationTester.php
	新文件:   assets/opencc/vendor/symfony/console/Tester/CommandCompletionTester.php
	新文件:   assets/opencc/vendor/symfony/console/Tester/CommandTester.php
	新文件:   assets/opencc/vendor/symfony/console/Tester/Constraint/CommandIsSuccessful.php
	新文件:   assets/opencc/vendor/symfony/console/Tester/TesterTrait.php
	新文件:   assets/opencc/vendor/symfony/console/composer.json
	新文件:   assets/opencc/vendor/symfony/deprecation-contracts/CHANGELOG.md
	新文件:   assets/opencc/vendor/symfony/deprecation-contracts/LICENSE
	新文件:   assets/opencc/vendor/symfony/deprecation-contracts/README.md
	新文件:   assets/opencc/vendor/symfony/deprecation-contracts/composer.json
	新文件:   assets/opencc/vendor/symfony/deprecation-contracts/function.php
	新文件:   assets/opencc/vendor/symfony/polyfill-ctype/Ctype.php
	新文件:   assets/opencc/vendor/symfony/polyfill-ctype/LICENSE
	新文件:   assets/opencc/vendor/symfony/polyfill-ctype/README.md
	新文件:   assets/opencc/vendor/symfony/polyfill-ctype/bootstrap.php
	新文件:   assets/opencc/vendor/symfony/polyfill-ctype/bootstrap80.php
	新文件:   assets/opencc/vendor/symfony/polyfill-ctype/composer.json
	新文件:   assets/opencc/vendor/symfony/polyfill-intl-grapheme/Grapheme.php
	新文件:   assets/opencc/vendor/symfony/polyfill-intl-grapheme/LICENSE
	新文件:   assets/opencc/vendor/symfony/polyfill-intl-grapheme/README.md
	新文件:   assets/opencc/vendor/symfony/polyfill-intl-grapheme/bootstrap.php
	新文件:   assets/opencc/vendor/symfony/polyfill-intl-grapheme/bootstrap80.php
	新文件:   assets/opencc/vendor/symfony/polyfill-intl-grapheme/composer.json
	新文件:   assets/opencc/vendor/symfony/polyfill-intl-normalizer/LICENSE
	新文件:   assets/opencc/vendor/symfony/polyfill-intl-normalizer/Normalizer.php
	新文件:   assets/opencc/vendor/symfony/polyfill-intl-normalizer/README.md
	新文件:   assets/opencc/vendor/symfony/polyfill-intl-normalizer/Resources/stubs/Normalizer.php
	新文件:   assets/opencc/vendor/symfony/polyfill-intl-normalizer/Resources/unidata/canonicalComposition.php
	新文件:   assets/opencc/vendor/symfony/polyfill-intl-normalizer/Resources/unidata/canonicalDecomposition.php
	新文件:   assets/opencc/vendor/symfony/polyfill-intl-normalizer/Resources/unidata/combiningClass.php
	新文件:   assets/opencc/vendor/symfony/polyfill-intl-normalizer/Resources/unidata/compatibilityDecomposition.php
	新文件:   assets/opencc/vendor/symfony/polyfill-intl-normalizer/bootstrap.php
	新文件:   assets/opencc/vendor/symfony/polyfill-intl-normalizer/bootstrap80.php
	新文件:   assets/opencc/vendor/symfony/polyfill-intl-normalizer/composer.json
	新文件:   assets/opencc/vendor/symfony/polyfill-mbstring/LICENSE
	新文件:   assets/opencc/vendor/symfony/polyfill-mbstring/Mbstring.php
	新文件:   assets/opencc/vendor/symfony/polyfill-mbstring/README.md
	新文件:   assets/opencc/vendor/symfony/polyfill-mbstring/Resources/unidata/caseFolding.php
	新文件:   assets/opencc/vendor/symfony/polyfill-mbstring/Resources/unidata/lowerCase.php
	新文件:   assets/opencc/vendor/symfony/polyfill-mbstring/Resources/unidata/titleCaseRegexp.php
	新文件:   assets/opencc/vendor/symfony/polyfill-mbstring/Resources/unidata/upperCase.php
	新文件:   assets/opencc/vendor/symfony/polyfill-mbstring/bootstrap.php
	新文件:   assets/opencc/vendor/symfony/polyfill-mbstring/bootstrap80.php
	新文件:   assets/opencc/vendor/symfony/polyfill-mbstring/composer.json
	新文件:   assets/opencc/vendor/symfony/process/CHANGELOG.md
	新文件:   assets/opencc/vendor/symfony/process/Exception/ExceptionInterface.php
	新文件:   assets/opencc/vendor/symfony/process/Exception/InvalidArgumentException.php
	新文件:   assets/opencc/vendor/symfony/process/Exception/LogicException.php
	新文件:   assets/opencc/vendor/symfony/process/Exception/ProcessFailedException.php
	新文件:   assets/opencc/vendor/symfony/process/Exception/ProcessSignaledException.php
	新文件:   assets/opencc/vendor/symfony/process/Exception/ProcessTimedOutException.php
	新文件:   assets/opencc/vendor/symfony/process/Exception/RunProcessFailedException.php
	新文件:   assets/opencc/vendor/symfony/process/Exception/RuntimeException.php
	新文件:   assets/opencc/vendor/symfony/process/ExecutableFinder.php
	新文件:   assets/opencc/vendor/symfony/process/InputStream.php
	新文件:   assets/opencc/vendor/symfony/process/LICENSE
	新文件:   assets/opencc/vendor/symfony/process/Messenger/RunProcessContext.php
	新文件:   assets/opencc/vendor/symfony/process/Messenger/RunProcessMessage.php
	新文件:   assets/opencc/vendor/symfony/process/Messenger/RunProcessMessageHandler.php
	新文件:   assets/opencc/vendor/symfony/process/PhpExecutableFinder.php
	新文件:   assets/opencc/vendor/symfony/process/PhpProcess.php
	新文件:   assets/opencc/vendor/symfony/process/PhpSubprocess.php
	新文件:   assets/opencc/vendor/symfony/process/Pipes/AbstractPipes.php
	新文件:   assets/opencc/vendor/symfony/process/Pipes/PipesInterface.php
	新文件:   assets/opencc/vendor/symfony/process/Pipes/UnixPipes.php
	新文件:   assets/opencc/vendor/symfony/process/Pipes/WindowsPipes.php
	新文件:   assets/opencc/vendor/symfony/process/Process.php
	新文件:   assets/opencc/vendor/symfony/process/ProcessUtils.php
	新文件:   assets/opencc/vendor/symfony/process/README.md
	新文件:   assets/opencc/vendor/symfony/process/composer.json
	新文件:   assets/opencc/vendor/symfony/service-contracts/Attribute/Required.php
	新文件:   assets/opencc/vendor/symfony/service-contracts/Attribute/SubscribedService.php
	新文件:   assets/opencc/vendor/symfony/service-contracts/CHANGELOG.md
	新文件:   assets/opencc/vendor/symfony/service-contracts/LICENSE
	新文件:   assets/opencc/vendor/symfony/service-contracts/README.md
	新文件:   assets/opencc/vendor/symfony/service-contracts/ResetInterface.php
	新文件:   assets/opencc/vendor/symfony/service-contracts/ServiceCollectionInterface.php
	新文件:   assets/opencc/vendor/symfony/service-contracts/ServiceLocatorTrait.php
	新文件:   assets/opencc/vendor/symfony/service-contracts/ServiceMethodsSubscriberTrait.php
	新文件:   assets/opencc/vendor/symfony/service-contracts/ServiceProviderInterface.php
	新文件:   assets/opencc/vendor/symfony/service-contracts/ServiceSubscriberInterface.php
	新文件:   assets/opencc/vendor/symfony/service-contracts/ServiceSubscriberTrait.php
	新文件:   assets/opencc/vendor/symfony/service-contracts/Test/ServiceLocatorTest.php
	新文件:   assets/opencc/vendor/symfony/service-contracts/Test/ServiceLocatorTestCase.php
	新文件:   assets/opencc/vendor/symfony/service-contracts/composer.json
	新文件:   assets/opencc/vendor/symfony/string/AbstractString.php
	新文件:   assets/opencc/vendor/symfony/string/AbstractUnicodeString.php
	新文件:   assets/opencc/vendor/symfony/string/ByteString.php
	新文件:   assets/opencc/vendor/symfony/string/CHANGELOG.md
	新文件:   assets/opencc/vendor/symfony/string/CodePointString.php
	新文件:   assets/opencc/vendor/symfony/string/Exception/ExceptionInterface.php
	新文件:   assets/opencc/vendor/symfony/string/Exception/InvalidArgumentException.php
	新文件:   assets/opencc/vendor/symfony/string/Exception/RuntimeException.php
	新文件:   assets/opencc/vendor/symfony/string/Inflector/EnglishInflector.php
	新文件:   assets/opencc/vendor/symfony/string/Inflector/FrenchInflector.php
	新文件:   assets/opencc/vendor/symfony/string/Inflector/InflectorInterface.php
	新文件:   assets/opencc/vendor/symfony/string/LICENSE
	新文件:   assets/opencc/vendor/symfony/string/LazyString.php
	新文件:   assets/opencc/vendor/symfony/string/README.md
	新文件:   assets/opencc/vendor/symfony/string/Resources/data/wcswidth_table_wide.php
	新文件:   assets/opencc/vendor/symfony/string/Resources/data/wcswidth_table_zero.php
	新文件:   assets/opencc/vendor/symfony/string/Resources/functions.php
	新文件:   assets/opencc/vendor/symfony/string/Slugger/AsciiSlugger.php
	新文件:   assets/opencc/vendor/symfony/string/Slugger/SluggerInterface.php
	新文件:   assets/opencc/vendor/symfony/string/UnicodeString.php
	新文件:   assets/opencc/vendor/symfony/string/composer.json
	新文件:   assets/phpliteadmin.php
	新文件:   config/Caddyfile
	新文件:   config/nginx.conf
	新文件:   cron.php
	新文件:   cron/requirements.txt
	新文件:   cron/update.py
	新文件:   index.php
	新文件:   manage.php
	新文件:   public.php
	新文件:   update.php
This commit is contained in:
mxd
2025-08-02 19:59:41 +08:00
parent ffb0d826bf
commit 57dae083a6
321 changed files with 180641 additions and 2 deletions

View File

@@ -1,3 +1,50 @@
# epgphp > Language: [English](README.md) [简体中文](README_zh-CN.md)
> [!IMPORTANT]
> The documentation for this project is still under preparation and is not yet complete.
[![GitHub License](https://img.shields.io/github/license/mxdabc/epgphp)
](https://www.gnu.org/licenses/gpl-2.0) ![Static Badge](https://img.shields.io/badge/redis-Optional-red) ![GitHub repo size](https://img.shields.io/github/repo-size/mxdabc/epgphp) ![Static Badge](https://img.shields.io/badge/php-%3E%3D7.2-blue) ![GitHub Repo stars](https://img.shields.io/github/stars/mxdabc/epgphp)
![Intro](https://socialify.git.ci/mxdabc/epgphp/image?description=1&descriptionEditable=PHP%20version%20of%20the%20EPG%20service%2C%20more%20lightweight.&font=Jost&forks=1&issues=1&language=1&name=1&owner=1&pulls=1&stargazers=1&theme=Auto)
# Lightweight PHP EPG Service
Welcome to the **Lightweight PHP EPG Service**! This project is a simple yet efficient Electronic Program Guide (EPG) service built with PHP. It is particularly suitable for EPG implementation in low-configuration servers, without Docker, and in scenarios requiring high concurrency.
> I was deleted the original version of the file link, symlink function. Generated directly in the root directory, there is no need for an extra layer. Suitable for host panel (e.g. Kangle, Baota) that do not have the `symlink()` function open, awesome!
## Features
- **Lightweight**: Minimal resource usage, optimized for performance.
- **Easy Setup**: Just a few steps to get started.
- **Flexible**: Easily customizable to suit your needs.
- **Cache**: Support cache software such as Redis and Memcached.
## Usage
1. **Add your EPG data**: Customize the `manage.php` file with your TV schedule data.
2. **Query the service**: Send HTTP GET requests to fetch EPG information.
3. **Customize**: Modify the code as needed to fit your specific requirements.
## Example
Heres a simple example of how to query the service:
```php
http://localhost:8000/index.php?channel=BBC&date=2024-08-14
http://localhost:8000/index.php?channel=BBC&date=20240814
```
## Contributing
Contributions are welcome! Feel free to submit issues, feature requests, or pull requests.
## License
Forked from: https://github.com/TakcC/PHP-EPG-Docker-Server
This repository is my own modified version, which is more suitable for use in scenarios without Docker and requiring high concurrency.
This project is licensed under the GPL-2.0 License. See the [LICENSE](LICENSE) file for more details.
PHP version of the EPG service, more lightweight. PHP版的EPG服务更轻量。

54
README_zh-CN.md Normal file
View File

@@ -0,0 +1,54 @@
> Language: [English](README.md) [简体中文](README_zh-CN.md)
> [!IMPORTANT]
> 本项目没有任何文档参考,目前正在编写中。
[![GitHub License](https://img.shields.io/github/license/mxdabc/epgphp)
](https://www.gnu.org/licenses/gpl-2.0) ![Static Badge](https://img.shields.io/badge/redis-可选-red) ![GitHub repo size](https://img.shields.io/github/repo-size/mxdabc/epgphp) ![Static Badge](https://img.shields.io/badge/php-%3E%3D7.2-blue) ![GitHub Repo stars](https://img.shields.io/github/stars/mxdabc/epgphp)
![Intro](https://socialify.git.ci/mxdabc/epgphp/image?description=1&descriptionEditable=PHP%E7%89%88%E7%9A%84EPG%E6%9C%8D%E5%8A%A1%EF%BC%8C%E6%9B%B4%E8%BD%BB%E9%87%8F%E3%80%82%20&font=Jost&forks=1&issues=1&language=1&name=1&owner=1&pulls=1&stargazers=1&theme=Auto)
# 轻量级 PHP 版 EPG 服务
欢迎使用 **轻量级 PHP 版 EPG 服务**这是一个简单而高效的电子节目指南EPG服务使用 PHP 构建。它设计得非常轻量级易于使用特别适合低配置服务器、没有Docker和需要高并发场景的 EPG 实现。
删除了原版本的文件链接symlink函数。直接在根目录生成完全没必要又多一层。适合没有开放`symlink()`函数的虚拟主机,有福了!
## 写在前面
遇到问题,理性反馈,不要做伸手党
## 功能特色
- **轻量级**:资源占用极少,性能优化良好。
- **简单安装**:几步即可开始使用。
- **灵活**:可以轻松自定义以满足您的需求。
- **带缓存队列支持**无需一直请求MySQL等数据库缓存高效。
## 使用说明
1. **添加您的 EPG 数据**:自定义 `manage.php` 文件,添加您的电视节目表数据。
2. **查询服务**:发送 HTTP GET 请求来获取 EPG 信息。
3. **自定义**:根据具体需求修改代码。
## 示例
以下是一个简单的查询示例:
```php
http://localhost:8000/index.php?channel=BBC&date=2024-08-14
http://localhost:8000/index.php?channel=BBC&date=20240814
```
## 贡献
欢迎贡献代码!您可以提交问题、功能请求或拉取请求。
## 许可证
Fork 自https://github.com/TakcC/PHP-EPG-Docker-Server
本仓库为衍生/二次开发版,更适合面板、虚拟主机、服务器、稳定性优先的用户部署。
本项目采用 GPL-2.0 许可证。有关详细信息,请参阅 [LICENSE](LICENSE) 文件。

33
assets/CHANGELOG.md Normal file
View File

@@ -0,0 +1,33 @@
## V4.0
1. 舍弃`symlink()`函数,直接在根目录生成`XMLTV`文件。
2. 添加Python脚本使其自动Cron适合没有权限执行cron.php的人。
3. 修复`manage.html`字符溢出。
4. 更新语法。
Summary: 总体来说更适合虚拟主机、面板用户可以托管至仅能使用PHP的网站。
## V3.1
1. 加入Nginx、Caddy服务器的配置文件示例更新了一些地方。
## V3.0
1. 引入Font Awesome.
2. 还是加上了phpliteadmin. 正在优化
## V2.0
1. 修改UI删去phpliteadmin、tinyfilemanager高危目录.
## V1.0
1. Original work: https://github.com/TakcC/PHP-EPG-Docker-Server
This repository is my own modified version, which is more suitable for use in scenarios without Docker and requiring high concurrency.
This project is licensed under the GPL-2.0 License. See the LICENSE file for more details.

1994
assets/Parsedown.php Normal file

File diff suppressed because it is too large Load Diff

194
assets/css/login.css Normal file
View File

@@ -0,0 +1,194 @@
@import url('https://gfonts.aby.pub/css?family=Raleway:400,700');
* {
box-sizing: border-box;
margin: 0;
padding: 0;
font-family: Raleway, sans-serif;
}
body {
background: linear-gradient(90deg, #C7C5F4, #776BCC);
height: 100vh;
overflow: hidden;
}
.container {
display: flex;
align-items: center;
justify-content: center;
height: 100vh;
}
.screen {
background: linear-gradient(90deg, #5D54A4, #7C78B8);
position: relative;
height: 600px;
width: 360px;
box-shadow: 0px 0px 24px #5C5696;
}
.screen__content {
z-index: 1;
position: relative;
height: 100%;
}
.screen__background {
position: absolute;
top: 0;
left: 0;
right: 0;
bottom: 0;
z-index: 0;
-webkit-clip-path: inset(0 0 0 0);
clip-path: inset(0 0 0 0);
}
.screen__background__shape {
transform: rotate(45deg);
position: absolute;
}
.screen__background__shape1 {
height: 520px;
width: 520px;
background: #FFF;
top: -50px;
right: 120px;
border-radius: 0 72px 0 0;
}
.screen__background__shape2 {
height: 220px;
width: 220px;
background: #6C63AC;
top: -172px;
right: 0;
border-radius: 32px;
}
.screen__background__shape3 {
height: 540px;
width: 190px;
background: linear-gradient(270deg, #5D54A4, #6A679E);
top: -24px;
right: 0;
border-radius: 32px;
}
.screen__background__shape4 {
height: 400px;
width: 200px;
background: #7E7BB9;
top: 420px;
right: 50px;
border-radius: 60px;
}
.login {
width: 320px;
padding: 30px;
padding-top: 156px;
}
.login__field {
padding: 20px 0px;
position: relative;
}
.login__icon {
position: absolute;
top: 30px;
color: #7875B5;
}
.login__input {
border: none;
border-bottom: 2px solid #D1D1D4;
background: none;
padding: 10px;
padding-left: 24px;
font-weight: 700;
width: 75%;
transition: .2s;
}
.login__input:active,
.login__input:focus,
login__input:hover {
outline: none;
border-bottom-color: #6A679E;
}
.login__submit {
background: #fff;
font-size: 14px;
margin-top: 30px;
padding: 16px 20px;
border-radius: 26px;
border: 1px solid #D4D3E8;
text-transform: uppercase;
font-weight: 700;
display: flex;
align-items: center;
width: 100%;
color: #4C489D;
box-shadow: 0px 2px 2px #5C5696;
cursor: pointer;
transition: .2s;
}
.login__submit:active,
login__submit:focus,
login__submit:hover {
border-color: #6A679E;
outline: none;
}
input[type="submit"],
.button__icon {
font-size: 24px;
margin-left: auto;
color: #7875B5;
}
.footer {
color: #ffffff;
position: fixed;
bottom: 10px;
width: 100%;
text-align: center;
text-decoration: none;
}
@media (max-width: 768px) {
.screen {
width: 100%;
height: 100%;
box-shadow: none;
}
.screen__background__shape1,
.screen__background__shape2,
.screen__background__shape3,
.screen__background__shape4 {
display: none;
}
.login {
width: 100%;
padding: 20px;
padding-top: 100px;
}
.login__input {
width: 100%;
}
}
@media (max-height: 600px) {
.login {
padding-top: 50px;
}
}

672
assets/css/manage.css Normal file
View File

@@ -0,0 +1,672 @@
@import url('https://gfonts.aby.pub/css2?family=DM+Sans:ital,opsz,wght@0,9..40,100..1000;1,9..40,100..1000&family=LXGW+WenKai+Mono+TC&display=swap');
body {
display: flex;
justify-content: center;
align-items: center;
height: 100vh;
margin: 0;
font-family: Tahoma, sans-serif;
background-color: #f0f0f0;
}
body.theme-transition {
transition: background-color 0.5s ease, color 0.5s ease;
}
.container {
background: white;
padding: 30px;
box-shadow: 0 0 15px rgba(0, 0, 0, 0.2);
border-radius: 5px;
width: 900px;
margin: auto;
}
textarea {
width: 100%;
padding: 5px;
line-height: 1.5;
font-size: 15px;
border: 1px solid #ccc;
border-radius: 5px;
box-sizing: border-box;
resize: none;
font-family: "Microsoft YaHei", "PingFang SC", "Hiragino Sans GB", Arial, sans-serif;
white-space: pre-wrap;
/* 保持空白字符和换行符,同时在内容超出容器宽度时换行 */
word-break: break-all;
/* 允许单词内断行 */
}
textarea:disabled {
opacity: 0.8;
}
textarea[id="gen_list_text"] {
height: 140px;
}
.form-row {
display: flex;
align-items: center;
margin-bottom: 10px;
}
.label-days-to-keep {
width: 98px;
}
.custom-margin1 {
margin-left: 189px;
}
.custom-margin2,
.custom-margin3 {
margin-left: 70px;
}
.form-row select,
.modal-content select,
input[type="time"] {
font-family: "Microsoft YaHei", "PingFang SC", "Hiragino Sans GB", Arial, sans-serif;
font-size: 15px;
border: 1px solid #ccc;
border-radius: 5px;
box-sizing: border-box;
width: 98px;
height: 32px;
margin-right: 12px;
text-align: center;
}
input[type="time"] {
width: 90px;
margin-right: 0px;
}
.form-row input[id="start_time"] {
margin-left: 292px;
}
.form-row input[id="end_time"],
select[id="interval_hour"] {
margin-left: 44px;
}
.form-row select[id="interval_hour"],
select[id="interval_minute"] {
width: 70px;
margin-right: 0px;
}
a,
.blue-span {
color: blue;
cursor: pointer;
text-decoration: none;
}
a:hover,
.blue-span:hover {
color: #0056b3;
}
.button-container {
display: flex;
gap: 15px;
margin: 0 auto;
align-items: center;
text-align: center;
justify-content: space-between;
}
.button-container a,
.button-container button,
.modal-content button,
input[type="submit"] {
padding: 10px;
background-color: #2196F3;
color: white;
border: none;
border-radius: 10px;
text-align: center;
cursor: pointer;
box-sizing: border-box;
align-items: center;
width: 100%;
font-size: 16px;
font-weight: bold;
}
.button-container a:hover,
.button-container button:hover,
.modal-content button:hover,
input[type="submit"]:hover {
background-color: #0b7dda;
}
input[type="submit"],
.button-container button[name="logoutbtn"],
.modal-content button {
background-color: #FF9800;
border-radius: 5px;
}
input[type="submit"]:hover,
.button-container button[name="logoutbtn"]:hover,
.modal-content button:hover {
background-color: #e68900;
}
button[id="deleteUnusedIcons"],
button[id="uploadAllIcons"],
button[id="showAllIcons"] {
display: flex;
height: 36px;
}
.button-container button[name="logoutbtn"] {
border-radius: 10px;
width: 300px;
}
input[type="text"] {
width: calc(100% - 22px);
padding: 10px;
margin-bottom: 10px;
border: 1px solid #ccc;
border-radius: 5px;
}
.flex-container {
display: flex;
justify-content: space-between;
gap: 20px;
}
.flex-item {
width: 48%;
}
.modal {
display: none;
/* 默认隐藏 */
position: fixed;
left: 0;
top: 0;
width: 100%;
height: 100%;
overflow: auto;
background-color: rgba(0, 0, 0, 0.4);
text-align: center;
}
.modal-content {
background-color: #fefefe;
display: inline-block;
padding: 20px;
border: 1px solid #888;
text-align: left;
border-radius: 10px;
position: relative;
box-shadow: 0 4px 8px 0 rgba(0, 0, 0, 0.2);
top: 50%;
transform: translateY(-50%);
width: 660px;
height: 530px;
}
.version-update-modal-content,
.help-modal-content {
padding-left: 25px;
}
.cron-log-modal-content {
width: 400px;
}
.update-log-modal-content {
width: 880px;
}
.live-source-modal-content {
width: 880px;
height: 630px;
}
.message-modal-content {
min-width: 150px;
width: auto;
height: auto;
line-height: 1.6;
}
.icon-modal-content {
width: 700px;
}
.close {
color: #aaa;
float: right;
font-size: 28px;
font-weight: bold;
}
.close:hover,
.close:focus {
color: black;
cursor: pointer;
}
.table-container {
height: 460px;
/* 固定高度 */
overflow-y: scroll;
/* 启用垂直滚动条 */
border: 1px solid #ccc;
border-radius: 5px;
font-size: 15px;
}
.table-container[id="channel-table-container"],
.table-container[id="icon-table-container"] {
height: 352px;
}
.table-container[id="channel-bind-epg-table-container"] {
height: 399px;
}
.table-container[id="channel-match-table-container"] {
height: 460px;
}
.table-container[id="live-source-table-container"] {
height: 410px;
}
#logTable,
#channelMatchTable,
#channelTable,
#iconTable,
#channelBindEPGTable,
#liveSourceTable {
width: 100%;
border-collapse: separate;
border-spacing: 0 0px;
/* 调整行之间的垂直间距 */
table-layout: fixed;
/* 固定表格布局,防止内容超出 */
}
#logTable,
#liveSourceTable {
border-spacing: 0 5px;
/* 调整行之间的垂直间距 */
}
#logTable th,
#logTable td,
#channelTable th,
#channelTable td,
#iconTable th,
#iconTable td,
#channelBindEPGTable th,
#channelBindEPGTable td,
#channelMatchTable th,
#channelMatchTable td,
#liveSourceTable th,
#liveSourceTable td {
border: 1px solid #ccc;
padding: 5px;
word-break: break-all;
/* 允许单词内断行 */
}
#channelTable th,
#channelTable td,
#iconTable th,
#iconTable td,
#channelMatchTable th,
#channelMatchTable td,
#channelBindEPGTable th,
#liveSourceTable th,
#liveSourceTable td {
text-align: center;
}
#logTable th:nth-child(1),
#logTable td:nth-child(1) {
width: 10%;
/* 第一列宽度 */
text-align: center;
}
#logTable th:nth-child(2) {
text-align: center;
/* 第二列表头居中 */
}
#channelTable th:nth-child(1),
#channelTable td:nth-child(1) {
width: 30%;
/* 第一列宽度 */
}
#iconTable th:nth-child(1),
#iconTable td:nth-child(1) {
width: 17%;
/* 第一列宽度 */
}
#iconTable th:nth-child(2),
#iconTable td:nth-child(2) {
width: 55%;
/* 第二列宽度 */
}
#iconTable th:nth-child(3),
#iconTable td:nth-child(3) {
width: 13%;
/* 第三列宽度 */
}
#channelMatchTable th:nth-child(4),
#channelMatchTable td:nth-child(4) {
width: 15%;
/* 第四列宽度 */
}
.row {
display: flex;
flex-wrap: nowrap;
/* 禁止换行 */
gap: 45px;
margin-bottom: 12px;
}
.column {
display: flex;
align-items: center;
flex: 1;
/* 每个列占据同等宽度 */
}
.row label {
white-space: nowrap;
/* 确保label不会换行 */
margin-right: 0px;
}
.row select,
.row textarea {
width: 100%;
margin-right: 0px;
}
.row textarea {
height: 32px;
line-height: 1.3;
white-space: nowrap;
/* 禁止换行 */
scrollbar-width: none;
/* 隐藏滚动条 */
}
/* 分页控件样式 */
#paginationContainer button {
width: 25px;
height: 20px;
margin: 0 2px;
padding: 0 0;
color: #aaaaaa;
background-color: #ffffff00;
cursor: pointer;
font-size: 15px;
}
#paginationContainer button.active,
#paginationContainer button:hover {
color: rgb(0, 0, 0);
}
#paginationContainer button[disabled] {
color: #bbb;
cursor: not-allowed;
}
/* 自定义滚动条样式 */
::-webkit-scrollbar {
width: 10px;
}
::-webkit-scrollbar-thumb {
background-color: #ddd;
border-radius: 4px;
cursor: default;
}
::-webkit-scrollbar-thumb:hover {
background-color: #ccc;
}
::-webkit-scrollbar-track {
background-color: #f5f5f5;
cursor: default;
}
.table-cell-disable {
font-weight: bold;
color: red;
background-color: #FFFFE0;
}
.table-cell-modified {
font-weight: bold;
color: red;
background-color: #DEFAFF;
}
.table-cell-clickable {
cursor: pointer;
user-select: none;
}
/* 主题切换按钮 */
.checkbox {
opacity: 0;
position: absolute;
}
.checkbox-label {
float: right;
margin-right: 5px;
margin-top: 20px;
background-color: #444;
width: 40px;
height: 16px;
border-radius: 50px;
position: relative;
padding: 5px;
cursor: pointer;
display: flex;
justify-content: space-between;
align-items: center;
transition: background-color 0.5s ease;
}
.checkbox-label i {
font-size: 18px;
color: #f39c12;
user-select: none;
transition: opacity 0.5s ease;
}
.checkbox-label .ball {
background-color: #fff;
width: 22px;
height: 22px;
position: absolute;
right: 2px;
/* 小球保持在右边 */
top: 2px;
border-radius: 50%;
transition: transform 0.5s ease;
}
.checkbox-label .label-text {
font-size: 7px;
color: #444;
font-weight: bold;
position: absolute;
top: 48%;
left: 75%;
transform: translateX(-50%) translateY(-50%);
z-index: 1;
/* 文字位于小球上面 */
user-select: none;
transition: opacity 0.5s ease;
}
/* 暗色模式 */
body.dark {
background-color: #121212;
color: #e0e0e0;
}
body.dark .container,
body.dark .modal-content {
background-color: #1e1e1e;
box-shadow: 0 0 15px rgba(255, 255, 255, 0.2);
}
body.dark textarea,
body.dark input[type="text"],
body.dark select,
body.dark input[type="time"] {
background-color: #333;
color: #e0e0e0;
border: 1px solid #555;
}
body.dark textarea:disabled {
background-color: #222;
color: #888;
}
body.dark a,
body.dark .blue-span {
color: #80bfff;
}
body.dark a:hover,
body.dark .blue-span:hover {
color: #3399ff;
}
body.dark .button-container a,
body.dark .button-container button {
background-color: #2d78b9;
color: #e0e0e0;
}
body.dark .button-container a:hover,
body.dark .button-container button:hover {
background-color: #1565c0;
}
body.dark input[type="submit"],
body.dark .button-container button[name="logoutbtn"],
body.dark .modal-content button {
background-color: #ce7c00;
color: #e0e0e0;
}
body.dark input[type="submit"]:hover,
body.dark .button-container button[name="logoutbtn"]:hover,
body.dark .modal-content button:hover {
background-color: #ba7000;
}
body.dark #paginationContainer button {
background-color: #1e1e1e;
color: #aaa;
}
body.dark #paginationContainer button.active,
body.dark #paginationContainer button:hover {
background-color: #333;
color: #fff;
}
body.dark #logTable th,
body.dark #logTable td,
body.dark #channelTable th,
body.dark #iconTable th,
body.dark #iconTable td,
body.dark #channelBindEPGTable th,
body.dark #channelBindEPGTable td,
body.dark #channelMatchTable th,
body.dark #channelMatchTable td,
body.dark #liveSourceTable th {
background-color: #2c2c2c;
color: #e0e0e0;
}
body.dark .close:hover,
body.dark .close:focus {
color: #e0e0e0;
}
body.dark img {
filter: brightness(0.9);
}
body.dark ::-webkit-scrollbar-thumb {
background-color: #555;
}
body.dark ::-webkit-scrollbar-thumb:hover {
background-color: #666;
}
body.dark ::-webkit-scrollbar-track {
background-color: #2a2a2a;
}
body.dark .table-cell-disable {
color: #ff7f7f;
background-color: #4a4a32;
}
body.dark .table-cell-modified {
color: #ff7f7f;
background-color: #3b616b;
}
body.dark .checkbox-label i,
body.dark .checkbox-label .label-text {
color: #eee;
}
body.dark .checkbox-label .ball {
background-color: #222;
}
.footer {
cursor: pointer;
color: #2a2a2a;
position: fixed;
bottom: 10px;
width: 100%;
text-align: center;
text-decoration: none;
}
.lxgw-wenkai-mono-tc-regular {
font-family: "LXGW WenKai Mono TC", consolas, Tahoma, monospace;
font-weight: 400;
font-style: normal;
}

31
assets/defaultConfig.json Normal file
View File

@@ -0,0 +1,31 @@
{
"xml_urls": [],
"days_to_keep": 7,
"start_time": "00:00",
"end_time": "23:59",
"channel_mappings": {
"CCTV$1": "regex:\/^CCTV[-\\s]*(\\d{1,2}(\\s*P(LUS)?|[K\\+])?)(?![\\s-]*(美洲|欧洲)).*\/i"
},
"channel_bind_epg": [],
"gen_xml": 1,
"include_future_only": 1,
"ret_default": 0,
"tvmao_default": 0,
"all_chs": 0,
"db_type": "mysql",
"gen_list_enable": 0,
"interval_time": 21600,
"mysql": {
"host": "localhost",
"dbname": "phpepg",
"username": "phpepg",
"password": "phpepg"
},
"live_source_auto_sync": 0,
"live_channel_name_process": 0,
"token": "",
"token_range": 1,
"default_icon": "",
"check_update": 1,
"manage_password": ""
}

2753
assets/defaultIconList.json Normal file

File diff suppressed because it is too large Load Diff

BIN
assets/html/favicon.ico Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.1 KiB

63
assets/html/login.html Normal file
View File

@@ -0,0 +1,63 @@
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<title>登录</title>
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="stylesheet" type="text/css" href="assets/css/login.css">
<link rel="icon" href="assets/html/favicon.ico" type="image/x-icon">
<link href="https://gfonts.aby.pub" rel="preconnect" crossorigin />
<link href="https://lf3-cdn-tos.bytecdntp.com" rel="preconnect" crossorigin />
<link href="https://lf3-cdn-tos.bytecdntp.com/cdn/expire-1-M/font-awesome/6.0.0/css/all.min.css" type="text/css" rel="stylesheet" />
</head>
<body>
<script>
(function() {
const savedTheme = localStorage.getItem('theme');
if (savedTheme) {
document.body.classList.add(savedTheme);
} else {
if (window.matchMedia('(prefers-color-scheme: dark)').matches) {
document.body.classList.add('dark');
}
}
})();
</script>
<div class="container">
<div class="screen">
<div class="screen__content">
<form method="post" class="login">
<h2>EPG System.</h2>
<!--
用户名暂未完成相关代码实现,先注释掉
<div class="login__field">
<i class="login__icon fas fa-user"></i>
<input type="text" class="login__input" placeholder="User name / Email">
</div>
-->
<div class="login__field">
<i class="login__icon fas fa-lock"></i>
<input type="password" id="password" name="password" class="login__input" placeholder="Password">
<input type="hidden" name="login" value="1">
</div>
<input type="submit" value="Log In" class="login__submit"></input>
</form>
<?php if (!empty($error)) echo "<p style='color:red;'>&nbsp;Error: $error</p>"; ?>
<?php echo $passwordChangedMessage; ?>
<?php echo $passwordChangeErrorMessage; ?>
</div>
<div class="screen__background">
<span class="screen__background__shape screen__background__shape4"></span>
<span class="screen__background__shape screen__background__shape3"></span>
<span class="screen__background__shape screen__background__shape2"></span>
<span class="screen__background__shape screen__background__shape1"></span>
</div>
</div>
</div>
<!-- 底部显示 -->
<footer>
<a href="https://github.com/mxdabc/epgphp" target="_blank" class="footer"><i class="fa-solid fa-server"></i>&nbsp;Crestekk Team EPG System for PHP.</a>
</footer>
<script src="static/js/mxd.js"></script>
</body>
</html>

595
assets/html/manage.html Normal file
View File

@@ -0,0 +1,595 @@
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<title>管理配置</title>
<link rel="stylesheet" type="text/css" href="assets/css/manage.css">
<link href="https://gfonts.aby.pub" rel="preconnect" crossorigin />
<link href="https://lf3-cdn-tos.bytecdntp.com" rel="preconnect" crossorigin />
<link href="https://lf3-cdn-tos.bytecdntp.com/cdn/expire-1-M/font-awesome/6.0.0/css/all.min.css" type="text/css" rel="stylesheet" />
<link rel="icon" href="assets/html/favicon.ico" type="image/x-icon">
</head>
<body class="lxgw-wenkai-mono-tc-regular">
<script>
(function() {
const savedTheme = localStorage.getItem('theme');
if (savedTheme) {
document.body.classList.add(savedTheme);
} else {
if (window.matchMedia('(prefers-color-scheme: dark)').matches) {
document.body.classList.add('dark');
}
}
})();
</script>
<div class="container">
<div>
<input type="checkbox" class="checkbox" id="themeSwitcher">
<label for="themeSwitcher" class="checkbox-label">
<i id="themeIcon"></i>
<span class="label-text"></span>
<span class="ball"></span>
</label>
<script>
const theme = localStorage.getItem('theme');
document.getElementById("themeIcon").className = `fas ${theme === 'dark' ? 'fa-moon' : theme === 'light' ? 'fa-sun' : 'fa-adjust'}`;
document.querySelector('.label-text').textContent = (theme === 'dark' ? 'Dark' : theme === 'light' ? 'Light' : 'Auto');
</script>
</div>
<h2>管理配置</h2>
<form method="POST" id="settingsForm">
<label for="xml_urls">【EPG地址】</label>
<span class="blue-span" id="channelbind" onclick="showModal('channelbindepg')">(频道指定源)</span>
<br><br>
<textarea id="xml_urls" name="xml_urls" style="height: 122px;"><?php echo implode("\n", array_map('trim', $Config['xml_urls'])); ?></textarea>
<br><br>
<div class="form-row">
<label for="days_to_keep" class="label-days-to-keep">数据保存天数</label>
<label for="start_time" class="label-time custom-margin1">【定时任务】: 开始时间</label>
<label for="end_time" class="label-time2 custom-margin2">结束时间</label>
<label for="interval_time" class="label-time3 custom-margin3">间隔周期选0小时0分钟取消</label>
</div>
<div class="form-row">
<select id="days_to_keep" name="days_to_keep" required>
<?php for ($i = 1; $i <= 30; $i++): ?>
<option value="<?php echo $i; ?>" <?php echo $Config['days_to_keep'] == $i ? 'selected' : ''; ?>>
<?php echo $i; ?>
</option>
<?php endfor; ?>
</select>
<input type="time" id="start_time" name="start_time" value="<?php echo $Config['start_time']; ?>" required>
<input type="time" id="end_time" name="end_time" value="<?php echo $Config['end_time']; ?>" required>
<!-- Interval Time Controls -->
<select id="interval_hour" name="interval_hour" required>
<?php for ($h = 0; $h < 24; $h++): ?>
<option value="<?php echo $h; ?>" <?php echo floor($Config['interval_time'] / 3600) == $h ? 'selected' : ''; ?>>
<?php echo $h; ?>
</option>
<?php endfor; ?>
</select> 小时
<select id="interval_minute" name="interval_minute" required>
<?php for ($m = 0; $m < 60; $m++): ?>
<option value="<?php echo $m; ?>" <?php echo (intval($Config['interval_time']) % 3600) / 60 == $m ? 'selected' : ''; ?>>
<?php echo $m; ?>
</option>
<?php endfor; ?>
</select> 分钟
</div><br>
<div class="flex-container">
<div class="flex-item" style="width: 100%;">
<label>【频道别名】</label>
<span class="blue-span" id="channelInfi" onclick="showModal('channel')">(频道管理)</span>
<span class="blue-span" id="iconInfo" onclick="showModal('icon')">(台标管理)</span>
<span class="blue-span" id="liveInfo" onclick="showModal('live')">(直播源管理)</span>
<br><br>
<textarea id="channel_mappings" name="channel_mappings" style="height: 142px;"><?php
echo implode("\n", array_map(function($search, $replace) {
return $search . ' => ' . $replace;
}, array_keys($Config['channel_mappings']), $Config['channel_mappings']));
?></textarea>
</div>
</div>
<br>
<input id="update_config" name="update_config" type="submit" value="保存配置">
<br><br>
<div class="button-container">
<a href="update.php" target="_blank">更新数据</a>
<button type="button" onclick="showModal('cron')">定时日志</button>
<button type="button" onclick="showModal('update')">更新日志</button>
<button type="button" onclick="showModal('moresetting')">更多设置</button>
<button type="button" name="logoutbtn" onclick="logout()">退出</button>
</div>
</form>
</div>
<!-- 底部显示 -->
<footer class="footer">
<a href="https://github.com/mxdabc/epgphp" target="_blank"><i class="fa-solid fa-server"></i>&nbsp;Crestekk Team EPG System for PHP.</a>
<i class="fa-solid fa-grip-lines-vertical"></i>
<a onclick="showVersionLog();">
<span id="version"><i class="fa-regular fa-newspaper"></i>&nbsp;V3.0
版本日志
</a>
<i class="fa-solid fa-grip-lines-vertical"></i>
<a onclick="showHelpModal();"><i class="fa-solid fa-circle-question"></i>&nbsp;使用说明</a>
</footer>
<!-- 消息模态框 -->
<div id="messageModal" class="modal">
<div class="modal-content message-modal-content">
<span class="close" style="position: absolute; top: 0px; right: 10px;">&times;</span>
<p id="messageModalMessage"></p>
</div>
</div>
<!-- 版本日志模态框 -->
<div id="versionLogModal" class="modal">
<div class="modal-content version-update-modal-content">
<span class="close">&times;</span>
<h2>版本日志</h2>
<p id="versionLogMessage" style="height: 455px; overflow: auto;"></p>
</div>
</div>
<!-- 使用说明模态框 -->
<div id="helpModal" class="modal">
<div class="modal-content help-modal-content">
<span class="close">&times;</span>
<h2>使用说明</h2>
<div style="height: 455px; overflow: auto; line-height: 1.7;">
保存设置快捷键Ctrl+S
<h3 style="line-height: 0.5;">EPG地址</h3>
支持 .xml 跟 .xml.gz 格式,地址前 # 临时停用,后 # 备注快捷键Ctrl+/<br>
自定义 UA url #备注 #自定义UAurl #备注 #OKhttp/1.31<br>
只提取部分频道频道名1, 频道名2 => 源地址<br>
示例tvmao, 频道id, [自定义:]频道id, ...<br>
示例cntv[:n], 频道id, [自定义:]频道id, ...<br>
[] 表示可选(使用时不包含[] :n 表示未来 n 天数据,缺省为 1<br>
频道指定 EPG 源:设置后,频道数据仅通过指定源更新<br>
优先级xml 源越靠前优先级越高tvmao 跟 cntv 强制覆盖已有数据
<h3 style="line-height: 0.5;">频道别名</h3>
格式:数据库频道名 => 频道别名1, 频道别名2, ...<br>
支持正则表达式,如:$1 => regex:/^iHOT(.*)/i 将前缀 iHOT 去掉<br>
建议使用「频道管理」页面修改
<h3 style="line-height: 0.5;">台标管理</h3>
默认列表:/assets/defaultList.json<br>
台标列表:/data/iconList.json<br>
优先读取 iconList.json<br>
清理:删除服务器中未被使用的台标文件<br>
全显:除了数据库频道列表外,同时显示无节目单的内置台标<br>
转存:将远程台标转存到服务器上
<h3 style="line-height: 0.5;">直播源管理</h3>
支持 .txt 和 .m3u 格式,光标离开后自动保存<br>
地址前 # 临时停用,后 # 备注并作为分组前缀快捷键Ctrl+/<br>
示例https://xxx.xx/xx.m3u #前缀1:<br>
自定义 UA url #备注 #自定义UAurl #备注 #OKhttp/1.31<br>
在生成 m3u 文件时「台标地址」、「tvg-id」、「tvg-name」字段可选<br>
转换直播源:<?php echo $serverUrl . '/index.php?token=' . $Config['token']; ?>&live=txt/m3u&url=xxx<br>
可添加 &latest=1 获取最新文件,不读取缓存<br>
同步:更新数据时,同步更新直播源数据,默认关闭<br>
改名:解析直播源数据时,使用数据库信息修正频道名,默认关闭<br>
清理:删除未出现在列表中的直播源文件缓存、未出现在频道列表中的修改记录<br>
停用:停用后不会出现在生成的直播源文件中,包括单个直播源<br>
保持:直播地址不变时,重新解析保持修改不变<br>
模板:生成直播源文件时仅包含模板数据,分组、频道名以模板为准<br>
分组为「default」时包含所有来源数据并使用原分组名称<br>
模糊匹配:默认开启,选「否」进行精准匹配<br>
线路备注:默认关闭,在直播地址后添加「$分组」<br>
<h3 style="line-height: 0.5;">其他设置</h3>
数据保存天数:清理超过设定天数的数据,包括节目单、定时日志、更新日志<br>
生成 xml 文件:默认生成包含预告数据的 xml 跟 xml.gz 文件,可自行关闭<br>
数据导入导出:包含 /data/ 文件夹的所有数据<br>
返回此频道暂无预告或者您配置有误。:无数据时返回「此频道暂无预告或者您配置有误。」用于回放,默认关闭<br>
Token 范围:点击后可修改 Token可设置范围默认「直播源」<br>
User-Agent 范围:点击后可修改 UA可用英文逗号分隔可设置范围默认「无」<br>
全转简中:节目单、描述信息转简体中文,默认关闭<br>
检查版本更新:进入设置界面后检测版本更新(仅提醒),默认打开<br>
限定频道:可粘贴直播地址进行解析,生成 xml 时包含该部分信息<br>
Memcached已移除相关设置默认打开缓存在更新数据时清除
</div>
</div>
</div>
<!-- 频道 EPG 模态框 -->
<div id="epgModal" class="modal">
<div class="modal-content epg-modal-content">
<span class="close">&times;</span>
<h2 id="epgTitle">频道名</h2>
<span id="epgSource" style="word-break: break-all;">来源</span>
<br><br>
<span id="epgDate">日期</span>
<span class="blue-span" id="prevDate" style="user-select: none; margin-left: 10px;">&#9664; 前一天</span>
<span class="blue-span" id="nextDate" style="user-select: none; margin-left: 10px;">后一天 &#9654;</span>
<br><br>
<textarea id="epgContent" readonly style="width: 100%; height: 380px;"></textarea>
</div>
</div>
<!-- 更新日志模态框 -->
<div id="updatelogModal" class="modal">
<div class="modal-content update-log-modal-content">
<span class="close">&times;</span>
<h2>数据库更新日志</h2>
<div class="table-container" id="log-table-container">
<table id="logTable">
<thead style="position: sticky; top: 0; background-color: white;">
<tr>
<th>时间</th>
<th>描述</th>
</tr>
</thead>
<tbody>
<!-- 数据由 JavaScript 动态生成 -->
</tbody>
</table>
</div>
</div>
</div>
<!-- 定时任务日志模态框 -->
<div id="cronlogModal" class="modal">
<div class="modal-content cron-log-modal-content">
<span class="close">&times;</span>
<h2>定时任务日志</h2>
<textarea id="cronLogContent" readonly style="width: 100%; height: 460px;"></textarea>
</div>
</div>
<!-- 频道列表模态框 -->
<div id="channelModal" class="modal">
<div class="modal-content channel-modal-content">
<span class="close">&times;</span>
<h2 id="channelModalTitle">频道列表</h2>
<input type="text" id="channelSearchInput" placeholder="搜索频道名..." onkeyup="filterChannels('channel')">
<div class="table-container" id="channel-table-container">
<table id="channelTable">
<thead style="position: sticky; top: 0; background-color: white;">
<tr>
<th>数据库频道名</th>
<th>频道别名</th>
</tr>
</thead>
<tbody>
<!-- 数据由 JavaScript 动态生成 -->
</tbody>
</table>
</div>
<br>
<button id="saveConfig" type="button" onclick="updateChannelMapping();">保存配置</button>
</div>
</div>
<!-- 台标列表模态框 -->
<div id="iconModal" class="modal">
<div class="modal-content icon-modal-content">
<span class="close">&times;</span>
<h2 id="iconModalTitle">频道列表</h2>
<div style="display: flex;">
<input type="text" id="iconSearchInput" placeholder="搜索频道名..." onkeyup="filterChannels('icon')" style="flex: 1; margin-right: 10px;">
<div style="width:auto; margin-right: 10px;">
<button id="deleteUnusedIcons" type="button" onclick="deleteUnusedIcons()">清理</button>
</div>
<div style="width:auto; margin-right: 10px;">
<button id="showAllIcons" type="button" onclick="showModal('allicon')">全显</button>
</div>
<div style="width:auto;">
<button id="uploadAllIcons" type="button" onclick="uploadAllIcons();">转存</button>
</div>
</div>
<div class="table-container" id="icon-table-container">
<table id="iconTable">
<thead style="position: sticky; top: 0; background-color: white;">
<tr>
<th>数据库频道名</th>
<th>台标地址</th>
<th>台标</th>
<th>上传</th>
</tr>
</thead>
<tbody>
<!-- 数据由 JavaScript 动态生成 -->
</tbody>
</table>
</div>
<br>
<button id="saveConfig" type="button" onclick="updateIconListJsonFile(notify = true);">保存配置</button>
</div>
</div>
<!-- 频道指定EPG模态框 -->
<div id="channelBindEPGModal" class="modal">
<div class="modal-content channel-bind-epg-modal-content">
<span class="close">&times;</span>
<h2>频道指定EPG源<span style="font-size: 14px;">(无指定则按靠前的源更新)</span></h2>
<div class="table-container" id="channel-bind-epg-table-container">
<table id="channelBindEPGTable">
<thead style="position: sticky; top: 0; background-color: white;">
<tr>
<th>指定EPG源</th>
<th>频道(可 , 分隔)</th>
</tr>
</thead>
<tbody>
<!-- 数据由 JavaScript 动态生成 -->
</tbody>
</table>
</div>
<br>
<button id="saveConfig" type="button" onclick="updateConfig();">保存配置</button>
</div>
</div>
<!-- 频道匹配结果模态框 -->
<div id="channelMatchModal" class="modal">
<div class="modal-content channel-match-modal-content">
<span class="close">&times;</span>
<h2>频道匹配结果</h2>
<div class="table-container" id="channel-match-table-container">
<table id="channelMatchTable">
<thead style="position: sticky; top: 0; background-color: white;">
<tr>
<th>原频道名</th>
<th>处理后频道名</th>
<th>匹配结果</th>
<th>备注</th>
</tr>
</thead>
<tbody>
<!-- 数据由 JavaScript 动态生成 -->
</tbody>
</table>
</div>
</div>
</div>
<!-- 直播源管理模态框 -->
<div id="liveSourceManageModal" class="modal">
<div class="modal-content live-source-modal-content">
<span class="close">&times;</span>
<!-- 输入框使用 textarea 用于输入直播源 URL -->
<div class="input-container">
<label for="sourceUrlTextarea">【直播源地址】</label><br>
<textarea id="sourceUrlTextarea" style="height: 102px;"></textarea>
</div>
<br>
<!-- 中间按钮区 -->
<div class="button-container" style="width: 90%;">
<input type="file" name="liveSourceFile" id="liveSourceFile" style="display: none;" accept=".m3u, .txt">
<button id="uploadSourceBtn" onclick="document.getElementById('liveSourceFile').click()">上传源</button>
<button id="parseSourceInfoBtn" onclick="parseSourceInfo()">解析源</button>
<button id="showLiveUrlBtn" onclick="showLiveUrl(`<?php echo $Config['token']; ?>`, `<?php echo $serverUrl; ?>`, `<?php echo $Config['token_range']; ?>`)">访问地址</button>
<button id="toggleLiveSourceSyncBtn" onclick="toggleStatus('toggleLiveSourceSyncBtn')">
同步: <?php echo (isset($Config['live_source_auto_sync']) && $Config['live_source_auto_sync'] == 1 ? '是' : '否'); ?>
</button>
<button id="toggleLiveChannelNameProcessBtn" onclick="toggleStatus('toggleLiveChannelNameProcessBtn')">
改名: <?php echo (isset($Config['live_channel_name_process']) && $Config['live_channel_name_process'] == 1 ? '是' : '否'); ?>
</button>
<button id="showLiveTemplateBtn" onclick="showLiveTemplate()">模板</button>
<button id="cleanUnusedSourceBtn" onclick="cleanUnusedSource()">清理</button>
<button id="saveSourceBtn" onclick="saveLiveSourceInfo()">保存</button>
</div>
<br>
<!-- 表格显示解析结果 -->
<div class="table-container" id="live-source-table-container">
<table id="liveSourceTable">
<thead class="sticky-header">
<tr>
<th style='width: 33px'>序号</th>
<th style='width: 10%'>分组</th>
<th style='width: 10%'>频道名</th>
<th>直播地址</th>
<th style='width: 20%'>台标地址<input type="checkbox" id="live_tvg_logo_enable"
value="<?php echo isset($Config['live_tvg_logo_enable']) ? $Config['live_tvg_logo_enable'] : 1; ?>"
<?php echo (!isset($Config['live_tvg_logo_enable']) || $Config['live_tvg_logo_enable'] == 1) ? 'checked' : ''; ?>
onchange="this.value = this.checked ? 1 : 0;">
</th>
<th style='width: 8%'>tvg-id<input type="checkbox" id="live_tvg_id_enable"
value="<?php echo isset($Config['live_tvg_id_enable']) ? $Config['live_tvg_id_enable'] : 1; ?>"
<?php echo (!isset($Config['live_tvg_id_enable']) || $Config['live_tvg_id_enable'] == 1) ? 'checked' : ''; ?>
onchange="this.value = this.checked ? 1 : 0;">
</th>
<th style='width: 12%'>tvg-name<input type="checkbox" id="live_tvg_name_enable"
value="<?php echo isset($Config['live_tvg_name_enable']) ? $Config['live_tvg_name_enable'] : 1; ?>"
<?php echo (!isset($Config['live_tvg_name_enable']) || $Config['live_tvg_name_enable'] == 1) ? 'checked' : ''; ?>
onchange="this.value = this.checked ? 1 : 0;">
</th>
<th style='width: 30px'>停用</th>
<th style='width: 30px'>保持</th>
</tr>
</thead>
<tbody>
<!-- 数据由 JavaScript 动态生成 -->
</tbody>
</table>
</div>
<!-- 分页控件 -->
<div id="paginationContainer" style="margin-top: 15px; text-align: center;">
<!-- 分页按钮由 JavaScript 动态生成 -->
</div>
</div>
</div>
<!-- 直播源模板模态框 -->
<div id="liveTemplateModal" class="modal">
<div class="modal-content live-template-modal-content">
<span class="close">&times;</span>
<h2>直播源模板<span style="font-size: 14px;">(生成直播源文件时仅包含以下数据)</span></h2>
<textarea id="liveTemplateTextarea" placeholder="#分组1&#10;频道1, 频道2&#10;频道3, 频道4&#10;&#10;#分组2&#10;&#10;#分组3, 来源1, 来源2&#10;&#10;#default, 来源3, 来源4&#10;&#10;..."
style="width: 100%; height: 350px;"></textarea><br>
<div class="row" style="margin-top: 15px; margin-bottom: 15px;">
<div class="column">
<label for="live_template_enable">启用模板:</label>
<select id="live_template_enable" name="live_template_enable" required>
<option value="1" <?php if (!isset($Config['live_template_enable']) || $Config['live_template_enable'] == 1) echo 'selected'; ?>>是</option>
<option value="0" <?php if (isset($Config['live_template_enable']) && $Config['live_template_enable'] == 0) echo 'selected'; ?>>否</option>
</select>
</div>
<div class="column">
<label for="live_fuzzy_match">模糊匹配:</label>
<select id="live_fuzzy_match" name="live_fuzzy_match" required>
<option value="1" <?php if (!isset($Config['live_fuzzy_match']) || $Config['live_fuzzy_match'] == 1) echo 'selected'; ?>>是</option>
<option value="0" <?php if (isset($Config['live_fuzzy_match']) && $Config['live_fuzzy_match'] == 0) echo 'selected'; ?>>否</option>
</select>
</div>
<div class="column">
<label for="live_url_comment">线路备注:</label>
<select id="live_url_comment" name="live_url_comment" required>
<option value="0" <?php if (!isset($Config['live_url_comment']) || $Config['live_url_comment'] == 0) echo 'selected'; ?>>关闭</option>
<option value="1" <?php if (isset($Config['live_url_comment']) && $Config['live_url_comment'] == 1) echo 'selected'; ?>>TXT</option>
<option value="2" <?php if (isset($Config['live_url_comment']) && $Config['live_url_comment'] == 2) echo 'selected'; ?>>M3U</option>
<option value="3" <?php if (isset($Config['live_url_comment']) && $Config['live_url_comment'] == 3) echo 'selected'; ?>>全部</option>
</select>
</div>
<div class="column">
</div>
</div>
<button id="saveConfig" type="button" onclick="saveLiveTemplate();">保存配置</button>
</div>
</div>
<!-- 更多设置模态框 -->
<div id="moreSettingModal" class="modal">
<div class="modal-content more-setting-modal-content">
<span class="close">&times;</span>
<h2>更多设置</h2>
<!-- 第一行 -->
<div class="row">
<div class="column">
<label for="gen_xml">生成 xml 文件:</label>
<select id="gen_xml" name="gen_xml" required>
<option value="1" <?php if ($Config['gen_xml'] == 1) echo 'selected'; ?>>是</option>
<option value="0" <?php if ($Config['gen_xml'] == 0) echo 'selected'; ?>>否</option>
</select>
</div>
<div class="column">
<label for="include_future_only">xml 内容:</label>
<select id="include_future_only" name="include_future_only" required>
<option value="1" <?php if ($Config['include_future_only'] == 1) echo 'selected'; ?>>预告数据</option>
<option value="0" <?php if ($Config['include_future_only'] == 0) echo 'selected'; ?>>所有数据</option>
</select>
</div>
<div class="column">
<form id="importForm" method="post" enctype="multipart/form-data" style="display: inline-block;">
<input type="file" name="importFile" id="importFile" style="display: none;" accept=".gz">
<input type="hidden" name="importExport" id="formImportExport" value="">
<span class="blue-span" id="import" onclick="document.getElementById('importFile').click()" style="margin-right: 20px;">数据导入</span>
<span class="blue-span" id="export" onclick="document.getElementById('importForm').submit()">数据导出</span>
</form>
</div>
</div>
<!-- 第二行 -->
<div class="row">
<div class="column">
<label for="ret_default">返回"无频道"字符串:</label>
<select id="ret_default" name="ret_default" required>
<option value="1" <?php if (!isset($Config['ret_default']) || $Config['ret_default'] == 1) echo 'selected'; ?>>是</option>
<option value="0" <?php if (isset($Config['ret_default']) && $Config['ret_default'] == 0) echo 'selected'; ?>>否</option>
</select>
</div>
<div class="column">
<label for="token_range"><span class="blue-span" id="change_token_span" onclick="changeTokenUA('token', `<?php echo $Config['token']; ?>`)">Token</span> 范围:</label>
<select id="token_range" name="token_range" required onchange="showTokenRangeMessage(`<?php echo $Config['token']; ?>`, `<?php echo $serverUrl; ?>`)">
<option value="0" <?php if (isset($Config['token_range']) && $Config['token_range'] == 0) echo 'selected'; ?>>无</option>
<option value="1" <?php if (!isset($Config['token_range']) || $Config['token_range'] == 1) echo 'selected'; ?>>直播源</option>
<option value="2" <?php if (isset($Config['token_range']) && $Config['token_range'] == 2) echo 'selected'; ?>>EPG</option>
<option value="3" <?php if (isset($Config['token_range']) && $Config['token_range'] == 3) echo 'selected'; ?>>全部</option>
</select>
</div>
<div class="column">
<label for="user_agent_range"><span class="blue-span" id="change_ua_span" onclick="changeTokenUA('user_agent', `<?php echo $Config['user_agent']; ?>`)">User-Agent</span> 范围:</label>
<select id="user_agent_range" name="user_agent_range" required">
<option value="0" <?php if (!isset($Config['user_agent_range']) || $Config['user_agent_range'] == 0) echo 'selected'; ?>>无</option>
<option value="1" <?php if (isset($Config['user_agent_range']) && $Config['user_agent_range'] == 1) echo 'selected'; ?>>直播源</option>
<option value="2" <?php if (isset($Config['user_agent_range']) && $Config['user_agent_range'] == 2) echo 'selected'; ?>>EPG</option>
<option value="3" <?php if (isset($Config['user_agent_range']) && $Config['user_agent_range'] == 3) echo 'selected'; ?>>全部</option>
</select>
</div>
</div>
<!-- 第三行 -->
<div class="row">
<div class="column">
<label for="all_chs" title="">全转简中:</label>
<select id="all_chs" name="all_chs" required>
<option value="1" <?php if (isset($Config['all_chs']) && $Config['all_chs'] == 1) echo 'selected'; ?>>是</option>
<option value="0" <?php if (!isset($Config['all_chs']) || $Config['all_chs'] == 0) echo 'selected'; ?>>否</option>
</select>
</div>
<div class="column">
<label for="db_type">数据库:</label>
<select id="db_type" name="db_type" required>
<option value="sqlite" <?php if (!isset($Config['db_type']) || $Config['db_type'] == 'sqlite') echo 'selected'; ?>>SQLite</option>
<option value="mysql" <?php if (isset($Config['db_type']) && $Config['db_type'] == 'mysql') echo 'selected'; ?>>MySQL</option>
</select>
</div>
<div class="column">
<label for="mysql_host">地址:</label>
<textarea id="mysql_host"><?php echo htmlspecialchars($Config['mysql']['host'] ?? ''); ?></textarea>
</div>
</div>
<!-- 第四行 -->
<div class="row">
<div class="column">
<label for="mysql_dbname">库名:</label>
<textarea id="mysql_dbname"><?php echo htmlspecialchars($Config['mysql']['dbname'] ?? ''); ?></textarea>
</div>
<div class="column">
<label for="mysql_username">用户:</label>
<textarea id="mysql_username"><?php echo htmlspecialchars($Config['mysql']['username'] ?? ''); ?></textarea>
</div>
<div class="column">
<label for="mysql_password">密码:</label>
<textarea id="mysql_password"><?php echo htmlspecialchars($Config['mysql']['password'] ?? ''); ?></textarea>
</div>
</div>
<!-- 第五行 -->
<div class="row">
<div class="column">
<label for="check_update">检查版本更新:</label>
<select id="check_update" name="check_update" required>
<option value="1" <?php if (!isset($Config['check_update']) || $Config['check_update'] == 1) echo 'selected'; ?>>是</option>
<option value="0" <?php if (isset($Config['check_update']) && $Config['check_update'] == 0) echo 'selected'; ?>>否</option>
</select>
</div>
<div class="column">
</div>
<div class="column">
</div>
</div>
<!-- 其他设置 -->
<label for="gen_list_text">仅生成以下频道数据:</label>
<select id="gen_list_enable" name="gen_list_enable" style="width: 60px; margin-right: 0px;" required>
<option value="1" <?php if (isset($Config['gen_list_enable']) && $Config['gen_list_enable'] == 1) echo 'selected'; ?>>是</option>
<option value="0" <?php if (!isset($Config['gen_list_enable']) || $Config['gen_list_enable'] == 0) echo 'selected'; ?>>否</option>
</select>
<span>
粘贴m3u、txt地址或内容<span class="blue-span" onclick="parseSource()">解析</span>
<span class="blue-span" onclick="showModal('channelmatch')">查看匹配</span>
</span>
<br>
<textarea id="gen_list_text" style="margin-top: 12px; margin-bottom: 12px;"></textarea><br>
<button id="saveConfig" type="button" onclick="setGenListAndUpdateConfig();">保存配置</button>
</div>
</div>
<script src="assets/js/manage.js"></script>
<script src="static/js/mxd.js"></script>
</body>
</html>

28
assets/js/console.js Normal file
View File

@@ -0,0 +1,28 @@
$(function () {
$("img.lazy").lazyload();
});
window.onload = function () {
const styleTitle1 = "font-size: 22px;font-weight: bold;color: rgb(0,0,139);font-family: 'Monaco', 'Menlo', 'Ubuntu Mono', 'Consolas', 'source-code-pro', monospace;";
const styleTitle2 = "font-size: 12px;color: rgb(0,0,139);font-family: 'Monaco', 'Menlo', 'Ubuntu Mono', 'Consolas', 'source-code-pro', monospace;";
const styleContent = "color: rgb(138,43,226);";
const title1 = "Crestekk Team EPG System for PHP.";
const title2 = `
╔═╗╦═╗╔═╗╔═╗╔╦╗╔═╗╦╔═╦╔═ ╔═╗╔═╗╔═╗
║ ╠╦╝║╣ ╚═╗ ║ ║╣ ╠╩╗╠╩╗ ║╣ ╠═╝║ ╦
╚═╝╩╚═╚═╝╚═╝ ╩ ╚═╝╩ ╩╩ ╩ ╚═╝╩ ╚═╝
███╗ ███╗██╗ ██╗██████╗ ██╗ ██╗███████╗ █████╗ ██╗ ██╗
████╗ ████║╚██╗██╔╝██╔══██╗╚██╗ ██╔╝██╔════╝██╔══██╗██║ ██║
██╔████╔██║ ╚███╔╝ ██║ ██║ ╚████╔╝ █████╗ ███████║███████║
██║╚██╔╝██║ ██╔██╗ ██║ ██║ ╚██╔╝ ██╔══╝ ██╔══██║██╔══██║
██║ ╚═╝ ██║██╔╝ ██╗██████╔╝ ██║ ███████╗██║ ██║██║ ██║
╚═╝ ╚═╝╚═╝ ╚═╝╚═════╝ ╚═╝ ╚══════╝╚═╝ ╚═╝╚═╝ ╚═╝
`;
const content = `\n\n版本: V3.1 \n主页: https://www.mxdyeah.top/ \nGithub: https://github.com/mxdabc/epgphp`;
console.info(`%c${title1} %c${title2} %c${content}`, styleTitle1, styleTitle2, styleContent);
}

1379
assets/js/manage.js Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,5 @@
{
"require": {
"overtrue/php-opencc": "^1.0"
}
}

621
assets/opencc/composer.lock generated Normal file
View File

@@ -0,0 +1,621 @@
{
"_readme": [
"This file locks the dependencies of your project to a known state",
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
"This file is @generated automatically"
],
"content-hash": "c67deeada1f1ba57cd16fd608b15f85e",
"packages": [
{
"name": "overtrue/php-opencc",
"version": "1.0.0",
"dist": {
"type": "zip",
"url": "https://mirrors.cloud.tencent.com/repository/composer/overtrue/php-opencc/1.0.0/overtrue-php-opencc-1.0.0.zip",
"reference": "747e9790ff59f589fca6748497242332553723b3",
"shasum": ""
},
"require": {
"ext-zip": "*",
"php": ">=8.0",
"symfony/console": "^5.4|^6.3",
"symfony/process": "^5.4|^6.3"
},
"require-dev": {
"brainmaestro/composer-git-hooks": "dev-master",
"jetbrains/phpstorm-attributes": "^1.0",
"laravel/pint": "^0.1|^1.10",
"mockery/mockery": "^1.2",
"phpunit/phpunit": "^9.0",
"vimeo/psalm": "^4.10"
},
"bin": [
"bin/opencc"
],
"type": "library",
"extra": {
"hooks": {
"pre-commit": [
"composer pint",
"composer test"
],
"pre-push": [
"composer pint",
"composer test"
]
}
},
"autoload": {
"psr-4": {
"Overtrue\\PHPOpenCC\\": "src"
}
},
"license": [
"MIT"
],
"authors": [
{
"name": "overtrue",
"email": "i@overtrue.me"
}
],
"description": "中文简繁转换,支持词汇级别的转换、异体字转换和地区习惯用词转换(中国大陆、台湾、香港、日本新字体)。基于 [BYVoid/OpenCC](https://github.com/BYVoid/OpenCC) 数据实现。",
"time": "2023-06-13T09:28:09+00:00"
},
{
"name": "psr/container",
"version": "2.0.2",
"dist": {
"type": "zip",
"url": "https://mirrors.cloud.tencent.com/repository/composer/psr/container/2.0.2/psr-container-2.0.2.zip",
"reference": "c71ecc56dfe541dbd90c5360474fbc405f8d5963",
"shasum": ""
},
"require": {
"php": ">=7.4.0"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "2.0.x-dev"
}
},
"autoload": {
"psr-4": {
"Psr\\Container\\": "src/"
}
},
"license": [
"MIT"
],
"authors": [
{
"name": "PHP-FIG",
"homepage": "https://www.php-fig.org/"
}
],
"description": "Common Container Interface (PHP FIG PSR-11)",
"homepage": "https://github.com/php-fig/container",
"keywords": [
"PSR-11",
"container",
"container-interface",
"container-interop",
"psr"
],
"time": "2021-11-05T16:47:00+00:00"
},
{
"name": "symfony/console",
"version": "v6.4.10",
"dist": {
"type": "zip",
"url": "https://mirrors.cloud.tencent.com/repository/composer/symfony/console/v6.4.10/symfony-console-v6.4.10.zip",
"reference": "504974cbe43d05f83b201d6498c206f16fc0cdbc",
"shasum": ""
},
"require": {
"php": ">=8.1",
"symfony/deprecation-contracts": "^2.5|^3",
"symfony/polyfill-mbstring": "~1.0",
"symfony/service-contracts": "^2.5|^3",
"symfony/string": "^5.4|^6.0|^7.0"
},
"conflict": {
"symfony/dependency-injection": "<5.4",
"symfony/dotenv": "<5.4",
"symfony/event-dispatcher": "<5.4",
"symfony/lock": "<5.4",
"symfony/process": "<5.4"
},
"provide": {
"psr/log-implementation": "1.0|2.0|3.0"
},
"require-dev": {
"psr/log": "^1|^2|^3",
"symfony/config": "^5.4|^6.0|^7.0",
"symfony/dependency-injection": "^5.4|^6.0|^7.0",
"symfony/event-dispatcher": "^5.4|^6.0|^7.0",
"symfony/http-foundation": "^6.4|^7.0",
"symfony/http-kernel": "^6.4|^7.0",
"symfony/lock": "^5.4|^6.0|^7.0",
"symfony/messenger": "^5.4|^6.0|^7.0",
"symfony/process": "^5.4|^6.0|^7.0",
"symfony/stopwatch": "^5.4|^6.0|^7.0",
"symfony/var-dumper": "^5.4|^6.0|^7.0"
},
"type": "library",
"autoload": {
"psr-4": {
"Symfony\\Component\\Console\\": ""
},
"exclude-from-classmap": [
"/Tests/"
]
},
"license": [
"MIT"
],
"authors": [
{
"name": "Fabien Potencier",
"email": "fabien@symfony.com"
},
{
"name": "Symfony Community",
"homepage": "https://symfony.com/contributors"
}
],
"description": "Eases the creation of beautiful and testable command line interfaces",
"homepage": "https://symfony.com",
"keywords": [
"cli",
"command-line",
"console",
"terminal"
],
"time": "2024-07-26T12:30:32+00:00"
},
{
"name": "symfony/deprecation-contracts",
"version": "v3.5.0",
"dist": {
"type": "zip",
"url": "https://mirrors.cloud.tencent.com/repository/composer/symfony/deprecation-contracts/v3.5.0/symfony-deprecation-contracts-v3.5.0.zip",
"reference": "0e0d29ce1f20deffb4ab1b016a7257c4f1e789a1",
"shasum": ""
},
"require": {
"php": ">=8.1"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-main": "3.5-dev"
},
"thanks": {
"name": "symfony/contracts",
"url": "https://github.com/symfony/contracts"
}
},
"autoload": {
"files": [
"function.php"
]
},
"license": [
"MIT"
],
"authors": [
{
"name": "Nicolas Grekas",
"email": "p@tchwork.com"
},
{
"name": "Symfony Community",
"homepage": "https://symfony.com/contributors"
}
],
"description": "A generic function and convention to trigger deprecation notices",
"homepage": "https://symfony.com",
"time": "2024-04-18T09:32:20+00:00"
},
{
"name": "symfony/polyfill-ctype",
"version": "v1.30.0",
"dist": {
"type": "zip",
"url": "https://mirrors.cloud.tencent.com/repository/composer/symfony/polyfill-ctype/v1.30.0/symfony-polyfill-ctype-v1.30.0.zip",
"reference": "0424dff1c58f028c451efff2045f5d92410bd540",
"shasum": ""
},
"require": {
"php": ">=7.1"
},
"provide": {
"ext-ctype": "*"
},
"suggest": {
"ext-ctype": "For best performance"
},
"type": "library",
"extra": {
"thanks": {
"name": "symfony/polyfill",
"url": "https://github.com/symfony/polyfill"
}
},
"autoload": {
"files": [
"bootstrap.php"
],
"psr-4": {
"Symfony\\Polyfill\\Ctype\\": ""
}
},
"license": [
"MIT"
],
"authors": [
{
"name": "Gert de Pagter",
"email": "BackEndTea@gmail.com"
},
{
"name": "Symfony Community",
"homepage": "https://symfony.com/contributors"
}
],
"description": "Symfony polyfill for ctype functions",
"homepage": "https://symfony.com",
"keywords": [
"compatibility",
"ctype",
"polyfill",
"portable"
],
"time": "2024-05-31T15:07:36+00:00"
},
{
"name": "symfony/polyfill-intl-grapheme",
"version": "v1.30.0",
"dist": {
"type": "zip",
"url": "https://mirrors.cloud.tencent.com/repository/composer/symfony/polyfill-intl-grapheme/v1.30.0/symfony-polyfill-intl-grapheme-v1.30.0.zip",
"reference": "64647a7c30b2283f5d49b874d84a18fc22054b7a",
"shasum": ""
},
"require": {
"php": ">=7.1"
},
"suggest": {
"ext-intl": "For best performance"
},
"type": "library",
"extra": {
"thanks": {
"name": "symfony/polyfill",
"url": "https://github.com/symfony/polyfill"
}
},
"autoload": {
"files": [
"bootstrap.php"
],
"psr-4": {
"Symfony\\Polyfill\\Intl\\Grapheme\\": ""
}
},
"license": [
"MIT"
],
"authors": [
{
"name": "Nicolas Grekas",
"email": "p@tchwork.com"
},
{
"name": "Symfony Community",
"homepage": "https://symfony.com/contributors"
}
],
"description": "Symfony polyfill for intl's grapheme_* functions",
"homepage": "https://symfony.com",
"keywords": [
"compatibility",
"grapheme",
"intl",
"polyfill",
"portable",
"shim"
],
"time": "2024-05-31T15:07:36+00:00"
},
{
"name": "symfony/polyfill-intl-normalizer",
"version": "v1.30.0",
"dist": {
"type": "zip",
"url": "https://mirrors.cloud.tencent.com/repository/composer/symfony/polyfill-intl-normalizer/v1.30.0/symfony-polyfill-intl-normalizer-v1.30.0.zip",
"reference": "a95281b0be0d9ab48050ebd988b967875cdb9fdb",
"shasum": ""
},
"require": {
"php": ">=7.1"
},
"suggest": {
"ext-intl": "For best performance"
},
"type": "library",
"extra": {
"thanks": {
"name": "symfony/polyfill",
"url": "https://github.com/symfony/polyfill"
}
},
"autoload": {
"files": [
"bootstrap.php"
],
"psr-4": {
"Symfony\\Polyfill\\Intl\\Normalizer\\": ""
},
"classmap": [
"Resources/stubs"
]
},
"license": [
"MIT"
],
"authors": [
{
"name": "Nicolas Grekas",
"email": "p@tchwork.com"
},
{
"name": "Symfony Community",
"homepage": "https://symfony.com/contributors"
}
],
"description": "Symfony polyfill for intl's Normalizer class and related functions",
"homepage": "https://symfony.com",
"keywords": [
"compatibility",
"intl",
"normalizer",
"polyfill",
"portable",
"shim"
],
"time": "2024-05-31T15:07:36+00:00"
},
{
"name": "symfony/polyfill-mbstring",
"version": "v1.30.0",
"dist": {
"type": "zip",
"url": "https://mirrors.cloud.tencent.com/repository/composer/symfony/polyfill-mbstring/v1.30.0/symfony-polyfill-mbstring-v1.30.0.zip",
"reference": "fd22ab50000ef01661e2a31d850ebaa297f8e03c",
"shasum": ""
},
"require": {
"php": ">=7.1"
},
"provide": {
"ext-mbstring": "*"
},
"suggest": {
"ext-mbstring": "For best performance"
},
"type": "library",
"extra": {
"thanks": {
"name": "symfony/polyfill",
"url": "https://github.com/symfony/polyfill"
}
},
"autoload": {
"files": [
"bootstrap.php"
],
"psr-4": {
"Symfony\\Polyfill\\Mbstring\\": ""
}
},
"license": [
"MIT"
],
"authors": [
{
"name": "Nicolas Grekas",
"email": "p@tchwork.com"
},
{
"name": "Symfony Community",
"homepage": "https://symfony.com/contributors"
}
],
"description": "Symfony polyfill for the Mbstring extension",
"homepage": "https://symfony.com",
"keywords": [
"compatibility",
"mbstring",
"polyfill",
"portable",
"shim"
],
"time": "2024-06-19T12:30:46+00:00"
},
{
"name": "symfony/process",
"version": "v6.4.8",
"dist": {
"type": "zip",
"url": "https://mirrors.cloud.tencent.com/repository/composer/symfony/process/v6.4.8/symfony-process-v6.4.8.zip",
"reference": "8d92dd79149f29e89ee0f480254db595f6a6a2c5",
"shasum": ""
},
"require": {
"php": ">=8.1"
},
"type": "library",
"autoload": {
"psr-4": {
"Symfony\\Component\\Process\\": ""
},
"exclude-from-classmap": [
"/Tests/"
]
},
"license": [
"MIT"
],
"authors": [
{
"name": "Fabien Potencier",
"email": "fabien@symfony.com"
},
{
"name": "Symfony Community",
"homepage": "https://symfony.com/contributors"
}
],
"description": "Executes commands in sub-processes",
"homepage": "https://symfony.com",
"time": "2024-05-31T14:49:08+00:00"
},
{
"name": "symfony/service-contracts",
"version": "v3.5.0",
"dist": {
"type": "zip",
"url": "https://mirrors.cloud.tencent.com/repository/composer/symfony/service-contracts/v3.5.0/symfony-service-contracts-v3.5.0.zip",
"reference": "bd1d9e59a81d8fa4acdcea3f617c581f7475a80f",
"shasum": ""
},
"require": {
"php": ">=8.1",
"psr/container": "^1.1|^2.0",
"symfony/deprecation-contracts": "^2.5|^3"
},
"conflict": {
"ext-psr": "<1.1|>=2"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-main": "3.5-dev"
},
"thanks": {
"name": "symfony/contracts",
"url": "https://github.com/symfony/contracts"
}
},
"autoload": {
"psr-4": {
"Symfony\\Contracts\\Service\\": ""
},
"exclude-from-classmap": [
"/Test/"
]
},
"license": [
"MIT"
],
"authors": [
{
"name": "Nicolas Grekas",
"email": "p@tchwork.com"
},
{
"name": "Symfony Community",
"homepage": "https://symfony.com/contributors"
}
],
"description": "Generic abstractions related to writing services",
"homepage": "https://symfony.com",
"keywords": [
"abstractions",
"contracts",
"decoupling",
"interfaces",
"interoperability",
"standards"
],
"time": "2024-04-18T09:32:20+00:00"
},
{
"name": "symfony/string",
"version": "v7.1.3",
"dist": {
"type": "zip",
"url": "https://mirrors.cloud.tencent.com/repository/composer/symfony/string/v7.1.3/symfony-string-v7.1.3.zip",
"reference": "ea272a882be7f20cad58d5d78c215001617b7f07",
"shasum": ""
},
"require": {
"php": ">=8.2",
"symfony/polyfill-ctype": "~1.8",
"symfony/polyfill-intl-grapheme": "~1.0",
"symfony/polyfill-intl-normalizer": "~1.0",
"symfony/polyfill-mbstring": "~1.0"
},
"conflict": {
"symfony/translation-contracts": "<2.5"
},
"require-dev": {
"symfony/emoji": "^7.1",
"symfony/error-handler": "^6.4|^7.0",
"symfony/http-client": "^6.4|^7.0",
"symfony/intl": "^6.4|^7.0",
"symfony/translation-contracts": "^2.5|^3.0",
"symfony/var-exporter": "^6.4|^7.0"
},
"type": "library",
"autoload": {
"files": [
"Resources/functions.php"
],
"psr-4": {
"Symfony\\Component\\String\\": ""
},
"exclude-from-classmap": [
"/Tests/"
]
},
"license": [
"MIT"
],
"authors": [
{
"name": "Nicolas Grekas",
"email": "p@tchwork.com"
},
{
"name": "Symfony Community",
"homepage": "https://symfony.com/contributors"
}
],
"description": "Provides an object-oriented API to strings and deals with bytes, UTF-8 code points and grapheme clusters in a unified way",
"homepage": "https://symfony.com",
"keywords": [
"grapheme",
"i18n",
"string",
"unicode",
"utf-8",
"utf8"
],
"time": "2024-07-22T10:25:37+00:00"
}
],
"packages-dev": [],
"aliases": [],
"minimum-stability": "stable",
"stability-flags": [],
"prefer-stable": false,
"prefer-lowest": false,
"platform": [],
"platform-dev": [],
"plugin-api-version": "2.6.0"
}

25
assets/opencc/vendor/autoload.php vendored Normal file
View File

@@ -0,0 +1,25 @@
<?php
// autoload.php @generated by Composer
if (PHP_VERSION_ID < 50600) {
if (!headers_sent()) {
header('HTTP/1.1 500 Internal Server Error');
}
$err = 'Composer 2.3.0 dropped support for autoloading on PHP <5.6 and you are running '.PHP_VERSION.', please upgrade PHP or use Composer 2.2 LTS via "composer self-update --2.2". Aborting.'.PHP_EOL;
if (!ini_get('display_errors')) {
if (PHP_SAPI === 'cli' || PHP_SAPI === 'phpdbg') {
fwrite(STDERR, $err);
} elseif (!headers_sent()) {
echo $err;
}
}
trigger_error(
$err,
E_USER_ERROR
);
}
require_once __DIR__ . '/composer/autoload_real.php';
return ComposerAutoloaderInit128c37fdd448b6871404289ced4b2d2a::getLoader();

119
assets/opencc/vendor/bin/opencc vendored Normal file
View File

@@ -0,0 +1,119 @@
#!/usr/bin/env php
<?php
/**
* Proxy PHP file generated by Composer
*
* This file includes the referenced bin path (../overtrue/php-opencc/bin/opencc)
* using a stream wrapper to prevent the shebang from being output on PHP<8
*
* @generated
*/
namespace Composer;
$GLOBALS['_composer_bin_dir'] = __DIR__;
$GLOBALS['_composer_autoload_path'] = __DIR__ . '/..'.'/autoload.php';
if (PHP_VERSION_ID < 80000) {
if (!class_exists('Composer\BinProxyWrapper')) {
/**
* @internal
*/
final class BinProxyWrapper
{
private $handle;
private $position;
private $realpath;
public function stream_open($path, $mode, $options, &$opened_path)
{
// get rid of phpvfscomposer:// prefix for __FILE__ & __DIR__ resolution
$opened_path = substr($path, 17);
$this->realpath = realpath($opened_path) ?: $opened_path;
$opened_path = $this->realpath;
$this->handle = fopen($this->realpath, $mode);
$this->position = 0;
return (bool) $this->handle;
}
public function stream_read($count)
{
$data = fread($this->handle, $count);
if ($this->position === 0) {
$data = preg_replace('{^#!.*\r?\n}', '', $data);
}
$this->position += strlen($data);
return $data;
}
public function stream_cast($castAs)
{
return $this->handle;
}
public function stream_close()
{
fclose($this->handle);
}
public function stream_lock($operation)
{
return $operation ? flock($this->handle, $operation) : true;
}
public function stream_seek($offset, $whence)
{
if (0 === fseek($this->handle, $offset, $whence)) {
$this->position = ftell($this->handle);
return true;
}
return false;
}
public function stream_tell()
{
return $this->position;
}
public function stream_eof()
{
return feof($this->handle);
}
public function stream_stat()
{
return array();
}
public function stream_set_option($option, $arg1, $arg2)
{
return true;
}
public function url_stat($path, $flags)
{
$path = substr($path, 17);
if (file_exists($path)) {
return stat($path);
}
return false;
}
}
}
if (
(function_exists('stream_get_wrappers') && in_array('phpvfscomposer', stream_get_wrappers(), true))
|| (function_exists('stream_wrapper_register') && stream_wrapper_register('phpvfscomposer', 'Composer\BinProxyWrapper'))
) {
return include("phpvfscomposer://" . __DIR__ . '/..'.'/overtrue/php-opencc/bin/opencc');
}
}
return include __DIR__ . '/..'.'/overtrue/php-opencc/bin/opencc';

View File

@@ -0,0 +1,579 @@
<?php
/*
* This file is part of Composer.
*
* (c) Nils Adermann <naderman@naderman.de>
* Jordi Boggiano <j.boggiano@seld.be>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Composer\Autoload;
/**
* ClassLoader implements a PSR-0, PSR-4 and classmap class loader.
*
* $loader = new \Composer\Autoload\ClassLoader();
*
* // register classes with namespaces
* $loader->add('Symfony\Component', __DIR__.'/component');
* $loader->add('Symfony', __DIR__.'/framework');
*
* // activate the autoloader
* $loader->register();
*
* // to enable searching the include path (eg. for PEAR packages)
* $loader->setUseIncludePath(true);
*
* In this example, if you try to use a class in the Symfony\Component
* namespace or one of its children (Symfony\Component\Console for instance),
* the autoloader will first look for the class under the component/
* directory, and it will then fallback to the framework/ directory if not
* found before giving up.
*
* This class is loosely based on the Symfony UniversalClassLoader.
*
* @author Fabien Potencier <fabien@symfony.com>
* @author Jordi Boggiano <j.boggiano@seld.be>
* @see https://www.php-fig.org/psr/psr-0/
* @see https://www.php-fig.org/psr/psr-4/
*/
class ClassLoader
{
/** @var \Closure(string):void */
private static $includeFile;
/** @var string|null */
private $vendorDir;
// PSR-4
/**
* @var array<string, array<string, int>>
*/
private $prefixLengthsPsr4 = array();
/**
* @var array<string, list<string>>
*/
private $prefixDirsPsr4 = array();
/**
* @var list<string>
*/
private $fallbackDirsPsr4 = array();
// PSR-0
/**
* List of PSR-0 prefixes
*
* Structured as array('F (first letter)' => array('Foo\Bar (full prefix)' => array('path', 'path2')))
*
* @var array<string, array<string, list<string>>>
*/
private $prefixesPsr0 = array();
/**
* @var list<string>
*/
private $fallbackDirsPsr0 = array();
/** @var bool */
private $useIncludePath = false;
/**
* @var array<string, string>
*/
private $classMap = array();
/** @var bool */
private $classMapAuthoritative = false;
/**
* @var array<string, bool>
*/
private $missingClasses = array();
/** @var string|null */
private $apcuPrefix;
/**
* @var array<string, self>
*/
private static $registeredLoaders = array();
/**
* @param string|null $vendorDir
*/
public function __construct($vendorDir = null)
{
$this->vendorDir = $vendorDir;
self::initializeIncludeClosure();
}
/**
* @return array<string, list<string>>
*/
public function getPrefixes()
{
if (!empty($this->prefixesPsr0)) {
return call_user_func_array('array_merge', array_values($this->prefixesPsr0));
}
return array();
}
/**
* @return array<string, list<string>>
*/
public function getPrefixesPsr4()
{
return $this->prefixDirsPsr4;
}
/**
* @return list<string>
*/
public function getFallbackDirs()
{
return $this->fallbackDirsPsr0;
}
/**
* @return list<string>
*/
public function getFallbackDirsPsr4()
{
return $this->fallbackDirsPsr4;
}
/**
* @return array<string, string> Array of classname => path
*/
public function getClassMap()
{
return $this->classMap;
}
/**
* @param array<string, string> $classMap Class to filename map
*
* @return void
*/
public function addClassMap(array $classMap)
{
if ($this->classMap) {
$this->classMap = array_merge($this->classMap, $classMap);
} else {
$this->classMap = $classMap;
}
}
/**
* Registers a set of PSR-0 directories for a given prefix, either
* appending or prepending to the ones previously set for this prefix.
*
* @param string $prefix The prefix
* @param list<string>|string $paths The PSR-0 root directories
* @param bool $prepend Whether to prepend the directories
*
* @return void
*/
public function add($prefix, $paths, $prepend = false)
{
$paths = (array) $paths;
if (!$prefix) {
if ($prepend) {
$this->fallbackDirsPsr0 = array_merge(
$paths,
$this->fallbackDirsPsr0
);
} else {
$this->fallbackDirsPsr0 = array_merge(
$this->fallbackDirsPsr0,
$paths
);
}
return;
}
$first = $prefix[0];
if (!isset($this->prefixesPsr0[$first][$prefix])) {
$this->prefixesPsr0[$first][$prefix] = $paths;
return;
}
if ($prepend) {
$this->prefixesPsr0[$first][$prefix] = array_merge(
$paths,
$this->prefixesPsr0[$first][$prefix]
);
} else {
$this->prefixesPsr0[$first][$prefix] = array_merge(
$this->prefixesPsr0[$first][$prefix],
$paths
);
}
}
/**
* Registers a set of PSR-4 directories for a given namespace, either
* appending or prepending to the ones previously set for this namespace.
*
* @param string $prefix The prefix/namespace, with trailing '\\'
* @param list<string>|string $paths The PSR-4 base directories
* @param bool $prepend Whether to prepend the directories
*
* @throws \InvalidArgumentException
*
* @return void
*/
public function addPsr4($prefix, $paths, $prepend = false)
{
$paths = (array) $paths;
if (!$prefix) {
// Register directories for the root namespace.
if ($prepend) {
$this->fallbackDirsPsr4 = array_merge(
$paths,
$this->fallbackDirsPsr4
);
} else {
$this->fallbackDirsPsr4 = array_merge(
$this->fallbackDirsPsr4,
$paths
);
}
} elseif (!isset($this->prefixDirsPsr4[$prefix])) {
// Register directories for a new namespace.
$length = strlen($prefix);
if ('\\' !== $prefix[$length - 1]) {
throw new \InvalidArgumentException("A non-empty PSR-4 prefix must end with a namespace separator.");
}
$this->prefixLengthsPsr4[$prefix[0]][$prefix] = $length;
$this->prefixDirsPsr4[$prefix] = $paths;
} elseif ($prepend) {
// Prepend directories for an already registered namespace.
$this->prefixDirsPsr4[$prefix] = array_merge(
$paths,
$this->prefixDirsPsr4[$prefix]
);
} else {
// Append directories for an already registered namespace.
$this->prefixDirsPsr4[$prefix] = array_merge(
$this->prefixDirsPsr4[$prefix],
$paths
);
}
}
/**
* Registers a set of PSR-0 directories for a given prefix,
* replacing any others previously set for this prefix.
*
* @param string $prefix The prefix
* @param list<string>|string $paths The PSR-0 base directories
*
* @return void
*/
public function set($prefix, $paths)
{
if (!$prefix) {
$this->fallbackDirsPsr0 = (array) $paths;
} else {
$this->prefixesPsr0[$prefix[0]][$prefix] = (array) $paths;
}
}
/**
* Registers a set of PSR-4 directories for a given namespace,
* replacing any others previously set for this namespace.
*
* @param string $prefix The prefix/namespace, with trailing '\\'
* @param list<string>|string $paths The PSR-4 base directories
*
* @throws \InvalidArgumentException
*
* @return void
*/
public function setPsr4($prefix, $paths)
{
if (!$prefix) {
$this->fallbackDirsPsr4 = (array) $paths;
} else {
$length = strlen($prefix);
if ('\\' !== $prefix[$length - 1]) {
throw new \InvalidArgumentException("A non-empty PSR-4 prefix must end with a namespace separator.");
}
$this->prefixLengthsPsr4[$prefix[0]][$prefix] = $length;
$this->prefixDirsPsr4[$prefix] = (array) $paths;
}
}
/**
* Turns on searching the include path for class files.
*
* @param bool $useIncludePath
*
* @return void
*/
public function setUseIncludePath($useIncludePath)
{
$this->useIncludePath = $useIncludePath;
}
/**
* Can be used to check if the autoloader uses the include path to check
* for classes.
*
* @return bool
*/
public function getUseIncludePath()
{
return $this->useIncludePath;
}
/**
* Turns off searching the prefix and fallback directories for classes
* that have not been registered with the class map.
*
* @param bool $classMapAuthoritative
*
* @return void
*/
public function setClassMapAuthoritative($classMapAuthoritative)
{
$this->classMapAuthoritative = $classMapAuthoritative;
}
/**
* Should class lookup fail if not found in the current class map?
*
* @return bool
*/
public function isClassMapAuthoritative()
{
return $this->classMapAuthoritative;
}
/**
* APCu prefix to use to cache found/not-found classes, if the extension is enabled.
*
* @param string|null $apcuPrefix
*
* @return void
*/
public function setApcuPrefix($apcuPrefix)
{
$this->apcuPrefix = function_exists('apcu_fetch') && filter_var(ini_get('apc.enabled'), FILTER_VALIDATE_BOOLEAN) ? $apcuPrefix : null;
}
/**
* The APCu prefix in use, or null if APCu caching is not enabled.
*
* @return string|null
*/
public function getApcuPrefix()
{
return $this->apcuPrefix;
}
/**
* Registers this instance as an autoloader.
*
* @param bool $prepend Whether to prepend the autoloader or not
*
* @return void
*/
public function register($prepend = false)
{
spl_autoload_register(array($this, 'loadClass'), true, $prepend);
if (null === $this->vendorDir) {
return;
}
if ($prepend) {
self::$registeredLoaders = array($this->vendorDir => $this) + self::$registeredLoaders;
} else {
unset(self::$registeredLoaders[$this->vendorDir]);
self::$registeredLoaders[$this->vendorDir] = $this;
}
}
/**
* Unregisters this instance as an autoloader.
*
* @return void
*/
public function unregister()
{
spl_autoload_unregister(array($this, 'loadClass'));
if (null !== $this->vendorDir) {
unset(self::$registeredLoaders[$this->vendorDir]);
}
}
/**
* Loads the given class or interface.
*
* @param string $class The name of the class
* @return true|null True if loaded, null otherwise
*/
public function loadClass($class)
{
if ($file = $this->findFile($class)) {
$includeFile = self::$includeFile;
$includeFile($file);
return true;
}
return null;
}
/**
* Finds the path to the file where the class is defined.
*
* @param string $class The name of the class
*
* @return string|false The path if found, false otherwise
*/
public function findFile($class)
{
// class map lookup
if (isset($this->classMap[$class])) {
return $this->classMap[$class];
}
if ($this->classMapAuthoritative || isset($this->missingClasses[$class])) {
return false;
}
if (null !== $this->apcuPrefix) {
$file = apcu_fetch($this->apcuPrefix.$class, $hit);
if ($hit) {
return $file;
}
}
$file = $this->findFileWithExtension($class, '.php');
// Search for Hack files if we are running on HHVM
if (false === $file && defined('HHVM_VERSION')) {
$file = $this->findFileWithExtension($class, '.hh');
}
if (null !== $this->apcuPrefix) {
apcu_add($this->apcuPrefix.$class, $file);
}
if (false === $file) {
// Remember that this class does not exist.
$this->missingClasses[$class] = true;
}
return $file;
}
/**
* Returns the currently registered loaders keyed by their corresponding vendor directories.
*
* @return array<string, self>
*/
public static function getRegisteredLoaders()
{
return self::$registeredLoaders;
}
/**
* @param string $class
* @param string $ext
* @return string|false
*/
private function findFileWithExtension($class, $ext)
{
// PSR-4 lookup
$logicalPathPsr4 = strtr($class, '\\', DIRECTORY_SEPARATOR) . $ext;
$first = $class[0];
if (isset($this->prefixLengthsPsr4[$first])) {
$subPath = $class;
while (false !== $lastPos = strrpos($subPath, '\\')) {
$subPath = substr($subPath, 0, $lastPos);
$search = $subPath . '\\';
if (isset($this->prefixDirsPsr4[$search])) {
$pathEnd = DIRECTORY_SEPARATOR . substr($logicalPathPsr4, $lastPos + 1);
foreach ($this->prefixDirsPsr4[$search] as $dir) {
if (file_exists($file = $dir . $pathEnd)) {
return $file;
}
}
}
}
}
// PSR-4 fallback dirs
foreach ($this->fallbackDirsPsr4 as $dir) {
if (file_exists($file = $dir . DIRECTORY_SEPARATOR . $logicalPathPsr4)) {
return $file;
}
}
// PSR-0 lookup
if (false !== $pos = strrpos($class, '\\')) {
// namespaced class name
$logicalPathPsr0 = substr($logicalPathPsr4, 0, $pos + 1)
. strtr(substr($logicalPathPsr4, $pos + 1), '_', DIRECTORY_SEPARATOR);
} else {
// PEAR-like class name
$logicalPathPsr0 = strtr($class, '_', DIRECTORY_SEPARATOR) . $ext;
}
if (isset($this->prefixesPsr0[$first])) {
foreach ($this->prefixesPsr0[$first] as $prefix => $dirs) {
if (0 === strpos($class, $prefix)) {
foreach ($dirs as $dir) {
if (file_exists($file = $dir . DIRECTORY_SEPARATOR . $logicalPathPsr0)) {
return $file;
}
}
}
}
}
// PSR-0 fallback dirs
foreach ($this->fallbackDirsPsr0 as $dir) {
if (file_exists($file = $dir . DIRECTORY_SEPARATOR . $logicalPathPsr0)) {
return $file;
}
}
// PSR-0 include paths.
if ($this->useIncludePath && $file = stream_resolve_include_path($logicalPathPsr0)) {
return $file;
}
return false;
}
/**
* @return void
*/
private static function initializeIncludeClosure()
{
if (self::$includeFile !== null) {
return;
}
/**
* Scope isolated include.
*
* Prevents access to $this/self from included files.
*
* @param string $file
* @return void
*/
self::$includeFile = \Closure::bind(static function($file) {
include $file;
}, null, null);
}
}

View File

@@ -0,0 +1,359 @@
<?php
/*
* This file is part of Composer.
*
* (c) Nils Adermann <naderman@naderman.de>
* Jordi Boggiano <j.boggiano@seld.be>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Composer;
use Composer\Autoload\ClassLoader;
use Composer\Semver\VersionParser;
/**
* This class is copied in every Composer installed project and available to all
*
* See also https://getcomposer.org/doc/07-runtime.md#installed-versions
*
* To require its presence, you can require `composer-runtime-api ^2.0`
*
* @final
*/
class InstalledVersions
{
/**
* @var mixed[]|null
* @psalm-var array{root: array{name: string, pretty_version: string, version: string, reference: string|null, type: string, install_path: string, aliases: string[], dev: bool}, versions: array<string, array{pretty_version?: string, version?: string, reference?: string|null, type?: string, install_path?: string, aliases?: string[], dev_requirement: bool, replaced?: string[], provided?: string[]}>}|array{}|null
*/
private static $installed;
/**
* @var bool|null
*/
private static $canGetVendors;
/**
* @var array[]
* @psalm-var array<string, array{root: array{name: string, pretty_version: string, version: string, reference: string|null, type: string, install_path: string, aliases: string[], dev: bool}, versions: array<string, array{pretty_version?: string, version?: string, reference?: string|null, type?: string, install_path?: string, aliases?: string[], dev_requirement: bool, replaced?: string[], provided?: string[]}>}>
*/
private static $installedByVendor = array();
/**
* Returns a list of all package names which are present, either by being installed, replaced or provided
*
* @return string[]
* @psalm-return list<string>
*/
public static function getInstalledPackages()
{
$packages = array();
foreach (self::getInstalled() as $installed) {
$packages[] = array_keys($installed['versions']);
}
if (1 === \count($packages)) {
return $packages[0];
}
return array_keys(array_flip(\call_user_func_array('array_merge', $packages)));
}
/**
* Returns a list of all package names with a specific type e.g. 'library'
*
* @param string $type
* @return string[]
* @psalm-return list<string>
*/
public static function getInstalledPackagesByType($type)
{
$packagesByType = array();
foreach (self::getInstalled() as $installed) {
foreach ($installed['versions'] as $name => $package) {
if (isset($package['type']) && $package['type'] === $type) {
$packagesByType[] = $name;
}
}
}
return $packagesByType;
}
/**
* Checks whether the given package is installed
*
* This also returns true if the package name is provided or replaced by another package
*
* @param string $packageName
* @param bool $includeDevRequirements
* @return bool
*/
public static function isInstalled($packageName, $includeDevRequirements = true)
{
foreach (self::getInstalled() as $installed) {
if (isset($installed['versions'][$packageName])) {
return $includeDevRequirements || !isset($installed['versions'][$packageName]['dev_requirement']) || $installed['versions'][$packageName]['dev_requirement'] === false;
}
}
return false;
}
/**
* Checks whether the given package satisfies a version constraint
*
* e.g. If you want to know whether version 2.3+ of package foo/bar is installed, you would call:
*
* Composer\InstalledVersions::satisfies(new VersionParser, 'foo/bar', '^2.3')
*
* @param VersionParser $parser Install composer/semver to have access to this class and functionality
* @param string $packageName
* @param string|null $constraint A version constraint to check for, if you pass one you have to make sure composer/semver is required by your package
* @return bool
*/
public static function satisfies(VersionParser $parser, $packageName, $constraint)
{
$constraint = $parser->parseConstraints((string) $constraint);
$provided = $parser->parseConstraints(self::getVersionRanges($packageName));
return $provided->matches($constraint);
}
/**
* Returns a version constraint representing all the range(s) which are installed for a given package
*
* It is easier to use this via isInstalled() with the $constraint argument if you need to check
* whether a given version of a package is installed, and not just whether it exists
*
* @param string $packageName
* @return string Version constraint usable with composer/semver
*/
public static function getVersionRanges($packageName)
{
foreach (self::getInstalled() as $installed) {
if (!isset($installed['versions'][$packageName])) {
continue;
}
$ranges = array();
if (isset($installed['versions'][$packageName]['pretty_version'])) {
$ranges[] = $installed['versions'][$packageName]['pretty_version'];
}
if (array_key_exists('aliases', $installed['versions'][$packageName])) {
$ranges = array_merge($ranges, $installed['versions'][$packageName]['aliases']);
}
if (array_key_exists('replaced', $installed['versions'][$packageName])) {
$ranges = array_merge($ranges, $installed['versions'][$packageName]['replaced']);
}
if (array_key_exists('provided', $installed['versions'][$packageName])) {
$ranges = array_merge($ranges, $installed['versions'][$packageName]['provided']);
}
return implode(' || ', $ranges);
}
throw new \OutOfBoundsException('Package "' . $packageName . '" is not installed');
}
/**
* @param string $packageName
* @return string|null If the package is being replaced or provided but is not really installed, null will be returned as version, use satisfies or getVersionRanges if you need to know if a given version is present
*/
public static function getVersion($packageName)
{
foreach (self::getInstalled() as $installed) {
if (!isset($installed['versions'][$packageName])) {
continue;
}
if (!isset($installed['versions'][$packageName]['version'])) {
return null;
}
return $installed['versions'][$packageName]['version'];
}
throw new \OutOfBoundsException('Package "' . $packageName . '" is not installed');
}
/**
* @param string $packageName
* @return string|null If the package is being replaced or provided but is not really installed, null will be returned as version, use satisfies or getVersionRanges if you need to know if a given version is present
*/
public static function getPrettyVersion($packageName)
{
foreach (self::getInstalled() as $installed) {
if (!isset($installed['versions'][$packageName])) {
continue;
}
if (!isset($installed['versions'][$packageName]['pretty_version'])) {
return null;
}
return $installed['versions'][$packageName]['pretty_version'];
}
throw new \OutOfBoundsException('Package "' . $packageName . '" is not installed');
}
/**
* @param string $packageName
* @return string|null If the package is being replaced or provided but is not really installed, null will be returned as reference
*/
public static function getReference($packageName)
{
foreach (self::getInstalled() as $installed) {
if (!isset($installed['versions'][$packageName])) {
continue;
}
if (!isset($installed['versions'][$packageName]['reference'])) {
return null;
}
return $installed['versions'][$packageName]['reference'];
}
throw new \OutOfBoundsException('Package "' . $packageName . '" is not installed');
}
/**
* @param string $packageName
* @return string|null If the package is being replaced or provided but is not really installed, null will be returned as install path. Packages of type metapackages also have a null install path.
*/
public static function getInstallPath($packageName)
{
foreach (self::getInstalled() as $installed) {
if (!isset($installed['versions'][$packageName])) {
continue;
}
return isset($installed['versions'][$packageName]['install_path']) ? $installed['versions'][$packageName]['install_path'] : null;
}
throw new \OutOfBoundsException('Package "' . $packageName . '" is not installed');
}
/**
* @return array
* @psalm-return array{name: string, pretty_version: string, version: string, reference: string|null, type: string, install_path: string, aliases: string[], dev: bool}
*/
public static function getRootPackage()
{
$installed = self::getInstalled();
return $installed[0]['root'];
}
/**
* Returns the raw installed.php data for custom implementations
*
* @deprecated Use getAllRawData() instead which returns all datasets for all autoloaders present in the process. getRawData only returns the first dataset loaded, which may not be what you expect.
* @return array[]
* @psalm-return array{root: array{name: string, pretty_version: string, version: string, reference: string|null, type: string, install_path: string, aliases: string[], dev: bool}, versions: array<string, array{pretty_version?: string, version?: string, reference?: string|null, type?: string, install_path?: string, aliases?: string[], dev_requirement: bool, replaced?: string[], provided?: string[]}>}
*/
public static function getRawData()
{
@trigger_error('getRawData only returns the first dataset loaded, which may not be what you expect. Use getAllRawData() instead which returns all datasets for all autoloaders present in the process.', E_USER_DEPRECATED);
if (null === self::$installed) {
// only require the installed.php file if this file is loaded from its dumped location,
// and not from its source location in the composer/composer package, see https://github.com/composer/composer/issues/9937
if (substr(__DIR__, -8, 1) !== 'C') {
self::$installed = include __DIR__ . '/installed.php';
} else {
self::$installed = array();
}
}
return self::$installed;
}
/**
* Returns the raw data of all installed.php which are currently loaded for custom implementations
*
* @return array[]
* @psalm-return list<array{root: array{name: string, pretty_version: string, version: string, reference: string|null, type: string, install_path: string, aliases: string[], dev: bool}, versions: array<string, array{pretty_version?: string, version?: string, reference?: string|null, type?: string, install_path?: string, aliases?: string[], dev_requirement: bool, replaced?: string[], provided?: string[]}>}>
*/
public static function getAllRawData()
{
return self::getInstalled();
}
/**
* Lets you reload the static array from another file
*
* This is only useful for complex integrations in which a project needs to use
* this class but then also needs to execute another project's autoloader in process,
* and wants to ensure both projects have access to their version of installed.php.
*
* A typical case would be PHPUnit, where it would need to make sure it reads all
* the data it needs from this class, then call reload() with
* `require $CWD/vendor/composer/installed.php` (or similar) as input to make sure
* the project in which it runs can then also use this class safely, without
* interference between PHPUnit's dependencies and the project's dependencies.
*
* @param array[] $data A vendor/composer/installed.php data set
* @return void
*
* @psalm-param array{root: array{name: string, pretty_version: string, version: string, reference: string|null, type: string, install_path: string, aliases: string[], dev: bool}, versions: array<string, array{pretty_version?: string, version?: string, reference?: string|null, type?: string, install_path?: string, aliases?: string[], dev_requirement: bool, replaced?: string[], provided?: string[]}>} $data
*/
public static function reload($data)
{
self::$installed = $data;
self::$installedByVendor = array();
}
/**
* @return array[]
* @psalm-return list<array{root: array{name: string, pretty_version: string, version: string, reference: string|null, type: string, install_path: string, aliases: string[], dev: bool}, versions: array<string, array{pretty_version?: string, version?: string, reference?: string|null, type?: string, install_path?: string, aliases?: string[], dev_requirement: bool, replaced?: string[], provided?: string[]}>}>
*/
private static function getInstalled()
{
if (null === self::$canGetVendors) {
self::$canGetVendors = method_exists('Composer\Autoload\ClassLoader', 'getRegisteredLoaders');
}
$installed = array();
if (self::$canGetVendors) {
foreach (ClassLoader::getRegisteredLoaders() as $vendorDir => $loader) {
if (isset(self::$installedByVendor[$vendorDir])) {
$installed[] = self::$installedByVendor[$vendorDir];
} elseif (is_file($vendorDir.'/composer/installed.php')) {
/** @var array{root: array{name: string, pretty_version: string, version: string, reference: string|null, type: string, install_path: string, aliases: string[], dev: bool}, versions: array<string, array{pretty_version?: string, version?: string, reference?: string|null, type?: string, install_path?: string, aliases?: string[], dev_requirement: bool, replaced?: string[], provided?: string[]}>} $required */
$required = require $vendorDir.'/composer/installed.php';
$installed[] = self::$installedByVendor[$vendorDir] = $required;
if (null === self::$installed && strtr($vendorDir.'/composer', '\\', '/') === strtr(__DIR__, '\\', '/')) {
self::$installed = $installed[count($installed) - 1];
}
}
}
}
if (null === self::$installed) {
// only require the installed.php file if this file is loaded from its dumped location,
// and not from its source location in the composer/composer package, see https://github.com/composer/composer/issues/9937
if (substr(__DIR__, -8, 1) !== 'C') {
/** @var array{root: array{name: string, pretty_version: string, version: string, reference: string|null, type: string, install_path: string, aliases: string[], dev: bool}, versions: array<string, array{pretty_version?: string, version?: string, reference?: string|null, type?: string, install_path?: string, aliases?: string[], dev_requirement: bool, replaced?: string[], provided?: string[]}>} $required */
$required = require __DIR__ . '/installed.php';
self::$installed = $required;
} else {
self::$installed = array();
}
}
if (self::$installed !== array()) {
$installed[] = self::$installed;
}
return $installed;
}
}

21
assets/opencc/vendor/composer/LICENSE vendored Normal file
View File

@@ -0,0 +1,21 @@
Copyright (c) Nils Adermann, Jordi Boggiano
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is furnished
to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.

View File

@@ -0,0 +1,11 @@
<?php
// autoload_classmap.php @generated by Composer
$vendorDir = dirname(__DIR__);
$baseDir = dirname($vendorDir);
return array(
'Composer\\InstalledVersions' => $vendorDir . '/composer/InstalledVersions.php',
'Normalizer' => $vendorDir . '/symfony/polyfill-intl-normalizer/Resources/stubs/Normalizer.php',
);

View File

@@ -0,0 +1,15 @@
<?php
// autoload_files.php @generated by Composer
$vendorDir = dirname(__DIR__);
$baseDir = dirname($vendorDir);
return array(
'6e3fae29631ef280660b3cdad06f25a8' => $vendorDir . '/symfony/deprecation-contracts/function.php',
'0e6d7bf4a5811bfa5cf40c5ccd6fae6a' => $vendorDir . '/symfony/polyfill-mbstring/bootstrap.php',
'320cde22f66dd4f5d3fd621d3e88b98f' => $vendorDir . '/symfony/polyfill-ctype/bootstrap.php',
'8825ede83f2f289127722d4e842cf7e8' => $vendorDir . '/symfony/polyfill-intl-grapheme/bootstrap.php',
'e69f7f6ee287b969198c3c9d6777bd38' => $vendorDir . '/symfony/polyfill-intl-normalizer/bootstrap.php',
'b6b991a57620e2fb6b2f66f03fe9ddc2' => $vendorDir . '/symfony/string/Resources/functions.php',
);

View File

@@ -0,0 +1,9 @@
<?php
// autoload_namespaces.php @generated by Composer
$vendorDir = dirname(__DIR__);
$baseDir = dirname($vendorDir);
return array(
);

View File

@@ -0,0 +1,19 @@
<?php
// autoload_psr4.php @generated by Composer
$vendorDir = dirname(__DIR__);
$baseDir = dirname($vendorDir);
return array(
'Symfony\\Polyfill\\Mbstring\\' => array($vendorDir . '/symfony/polyfill-mbstring'),
'Symfony\\Polyfill\\Intl\\Normalizer\\' => array($vendorDir . '/symfony/polyfill-intl-normalizer'),
'Symfony\\Polyfill\\Intl\\Grapheme\\' => array($vendorDir . '/symfony/polyfill-intl-grapheme'),
'Symfony\\Polyfill\\Ctype\\' => array($vendorDir . '/symfony/polyfill-ctype'),
'Symfony\\Contracts\\Service\\' => array($vendorDir . '/symfony/service-contracts'),
'Symfony\\Component\\String\\' => array($vendorDir . '/symfony/string'),
'Symfony\\Component\\Process\\' => array($vendorDir . '/symfony/process'),
'Symfony\\Component\\Console\\' => array($vendorDir . '/symfony/console'),
'Psr\\Container\\' => array($vendorDir . '/psr/container/src'),
'Overtrue\\PHPOpenCC\\' => array($vendorDir . '/overtrue/php-opencc/src'),
);

View File

@@ -0,0 +1,50 @@
<?php
// autoload_real.php @generated by Composer
class ComposerAutoloaderInit128c37fdd448b6871404289ced4b2d2a
{
private static $loader;
public static function loadClassLoader($class)
{
if ('Composer\Autoload\ClassLoader' === $class) {
require __DIR__ . '/ClassLoader.php';
}
}
/**
* @return \Composer\Autoload\ClassLoader
*/
public static function getLoader()
{
if (null !== self::$loader) {
return self::$loader;
}
require __DIR__ . '/platform_check.php';
spl_autoload_register(array('ComposerAutoloaderInit128c37fdd448b6871404289ced4b2d2a', 'loadClassLoader'), true, true);
self::$loader = $loader = new \Composer\Autoload\ClassLoader(\dirname(__DIR__));
spl_autoload_unregister(array('ComposerAutoloaderInit128c37fdd448b6871404289ced4b2d2a', 'loadClassLoader'));
require __DIR__ . '/autoload_static.php';
call_user_func(\Composer\Autoload\ComposerStaticInit128c37fdd448b6871404289ced4b2d2a::getInitializer($loader));
$loader->register(true);
$filesToLoad = \Composer\Autoload\ComposerStaticInit128c37fdd448b6871404289ced4b2d2a::$files;
$requireFile = \Closure::bind(static function ($fileIdentifier, $file) {
if (empty($GLOBALS['__composer_autoload_files'][$fileIdentifier])) {
$GLOBALS['__composer_autoload_files'][$fileIdentifier] = true;
require $file;
}
}, null, null);
foreach ($filesToLoad as $fileIdentifier => $file) {
$requireFile($fileIdentifier, $file);
}
return $loader;
}
}

View File

@@ -0,0 +1,97 @@
<?php
// autoload_static.php @generated by Composer
namespace Composer\Autoload;
class ComposerStaticInit128c37fdd448b6871404289ced4b2d2a
{
public static $files = array (
'6e3fae29631ef280660b3cdad06f25a8' => __DIR__ . '/..' . '/symfony/deprecation-contracts/function.php',
'0e6d7bf4a5811bfa5cf40c5ccd6fae6a' => __DIR__ . '/..' . '/symfony/polyfill-mbstring/bootstrap.php',
'320cde22f66dd4f5d3fd621d3e88b98f' => __DIR__ . '/..' . '/symfony/polyfill-ctype/bootstrap.php',
'8825ede83f2f289127722d4e842cf7e8' => __DIR__ . '/..' . '/symfony/polyfill-intl-grapheme/bootstrap.php',
'e69f7f6ee287b969198c3c9d6777bd38' => __DIR__ . '/..' . '/symfony/polyfill-intl-normalizer/bootstrap.php',
'b6b991a57620e2fb6b2f66f03fe9ddc2' => __DIR__ . '/..' . '/symfony/string/Resources/functions.php',
);
public static $prefixLengthsPsr4 = array (
'S' =>
array (
'Symfony\\Polyfill\\Mbstring\\' => 26,
'Symfony\\Polyfill\\Intl\\Normalizer\\' => 33,
'Symfony\\Polyfill\\Intl\\Grapheme\\' => 31,
'Symfony\\Polyfill\\Ctype\\' => 23,
'Symfony\\Contracts\\Service\\' => 26,
'Symfony\\Component\\String\\' => 25,
'Symfony\\Component\\Process\\' => 26,
'Symfony\\Component\\Console\\' => 26,
),
'P' =>
array (
'Psr\\Container\\' => 14,
),
'O' =>
array (
'Overtrue\\PHPOpenCC\\' => 19,
),
);
public static $prefixDirsPsr4 = array (
'Symfony\\Polyfill\\Mbstring\\' =>
array (
0 => __DIR__ . '/..' . '/symfony/polyfill-mbstring',
),
'Symfony\\Polyfill\\Intl\\Normalizer\\' =>
array (
0 => __DIR__ . '/..' . '/symfony/polyfill-intl-normalizer',
),
'Symfony\\Polyfill\\Intl\\Grapheme\\' =>
array (
0 => __DIR__ . '/..' . '/symfony/polyfill-intl-grapheme',
),
'Symfony\\Polyfill\\Ctype\\' =>
array (
0 => __DIR__ . '/..' . '/symfony/polyfill-ctype',
),
'Symfony\\Contracts\\Service\\' =>
array (
0 => __DIR__ . '/..' . '/symfony/service-contracts',
),
'Symfony\\Component\\String\\' =>
array (
0 => __DIR__ . '/..' . '/symfony/string',
),
'Symfony\\Component\\Process\\' =>
array (
0 => __DIR__ . '/..' . '/symfony/process',
),
'Symfony\\Component\\Console\\' =>
array (
0 => __DIR__ . '/..' . '/symfony/console',
),
'Psr\\Container\\' =>
array (
0 => __DIR__ . '/..' . '/psr/container/src',
),
'Overtrue\\PHPOpenCC\\' =>
array (
0 => __DIR__ . '/..' . '/overtrue/php-opencc/src',
),
);
public static $classMap = array (
'Composer\\InstalledVersions' => __DIR__ . '/..' . '/composer/InstalledVersions.php',
'Normalizer' => __DIR__ . '/..' . '/symfony/polyfill-intl-normalizer/Resources/stubs/Normalizer.php',
);
public static function getInitializer(ClassLoader $loader)
{
return \Closure::bind(function () use ($loader) {
$loader->prefixLengthsPsr4 = ComposerStaticInit128c37fdd448b6871404289ced4b2d2a::$prefixLengthsPsr4;
$loader->prefixDirsPsr4 = ComposerStaticInit128c37fdd448b6871404289ced4b2d2a::$prefixDirsPsr4;
$loader->classMap = ComposerStaticInit128c37fdd448b6871404289ced4b2d2a::$classMap;
}, null, ClassLoader::class);
}
}

View File

@@ -0,0 +1,641 @@
{
"packages": [
{
"name": "overtrue/php-opencc",
"version": "1.0.0",
"version_normalized": "1.0.0.0",
"dist": {
"type": "zip",
"url": "https://mirrors.cloud.tencent.com/repository/composer/overtrue/php-opencc/1.0.0/overtrue-php-opencc-1.0.0.zip",
"reference": "747e9790ff59f589fca6748497242332553723b3",
"shasum": ""
},
"require": {
"ext-zip": "*",
"php": ">=8.0",
"symfony/console": "^5.4|^6.3",
"symfony/process": "^5.4|^6.3"
},
"require-dev": {
"brainmaestro/composer-git-hooks": "dev-master",
"jetbrains/phpstorm-attributes": "^1.0",
"laravel/pint": "^0.1|^1.10",
"mockery/mockery": "^1.2",
"phpunit/phpunit": "^9.0",
"vimeo/psalm": "^4.10"
},
"time": "2023-06-13T09:28:09+00:00",
"bin": [
"bin/opencc"
],
"type": "library",
"extra": {
"hooks": {
"pre-commit": [
"composer pint",
"composer test"
],
"pre-push": [
"composer pint",
"composer test"
]
}
},
"installation-source": "dist",
"autoload": {
"psr-4": {
"Overtrue\\PHPOpenCC\\": "src"
}
},
"license": [
"MIT"
],
"authors": [
{
"name": "overtrue",
"email": "i@overtrue.me"
}
],
"description": "中文简繁转换,支持词汇级别的转换、异体字转换和地区习惯用词转换(中国大陆、台湾、香港、日本新字体)。基于 [BYVoid/OpenCC](https://github.com/BYVoid/OpenCC) 数据实现。",
"install-path": "../overtrue/php-opencc"
},
{
"name": "psr/container",
"version": "2.0.2",
"version_normalized": "2.0.2.0",
"dist": {
"type": "zip",
"url": "https://mirrors.cloud.tencent.com/repository/composer/psr/container/2.0.2/psr-container-2.0.2.zip",
"reference": "c71ecc56dfe541dbd90c5360474fbc405f8d5963",
"shasum": ""
},
"require": {
"php": ">=7.4.0"
},
"time": "2021-11-05T16:47:00+00:00",
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "2.0.x-dev"
}
},
"installation-source": "dist",
"autoload": {
"psr-4": {
"Psr\\Container\\": "src/"
}
},
"license": [
"MIT"
],
"authors": [
{
"name": "PHP-FIG",
"homepage": "https://www.php-fig.org/"
}
],
"description": "Common Container Interface (PHP FIG PSR-11)",
"homepage": "https://github.com/php-fig/container",
"keywords": [
"PSR-11",
"container",
"container-interface",
"container-interop",
"psr"
],
"install-path": "../psr/container"
},
{
"name": "symfony/console",
"version": "v6.4.10",
"version_normalized": "6.4.10.0",
"dist": {
"type": "zip",
"url": "https://mirrors.cloud.tencent.com/repository/composer/symfony/console/v6.4.10/symfony-console-v6.4.10.zip",
"reference": "504974cbe43d05f83b201d6498c206f16fc0cdbc",
"shasum": ""
},
"require": {
"php": ">=8.1",
"symfony/deprecation-contracts": "^2.5|^3",
"symfony/polyfill-mbstring": "~1.0",
"symfony/service-contracts": "^2.5|^3",
"symfony/string": "^5.4|^6.0|^7.0"
},
"conflict": {
"symfony/dependency-injection": "<5.4",
"symfony/dotenv": "<5.4",
"symfony/event-dispatcher": "<5.4",
"symfony/lock": "<5.4",
"symfony/process": "<5.4"
},
"provide": {
"psr/log-implementation": "1.0|2.0|3.0"
},
"require-dev": {
"psr/log": "^1|^2|^3",
"symfony/config": "^5.4|^6.0|^7.0",
"symfony/dependency-injection": "^5.4|^6.0|^7.0",
"symfony/event-dispatcher": "^5.4|^6.0|^7.0",
"symfony/http-foundation": "^6.4|^7.0",
"symfony/http-kernel": "^6.4|^7.0",
"symfony/lock": "^5.4|^6.0|^7.0",
"symfony/messenger": "^5.4|^6.0|^7.0",
"symfony/process": "^5.4|^6.0|^7.0",
"symfony/stopwatch": "^5.4|^6.0|^7.0",
"symfony/var-dumper": "^5.4|^6.0|^7.0"
},
"time": "2024-07-26T12:30:32+00:00",
"type": "library",
"installation-source": "dist",
"autoload": {
"psr-4": {
"Symfony\\Component\\Console\\": ""
},
"exclude-from-classmap": [
"/Tests/"
]
},
"license": [
"MIT"
],
"authors": [
{
"name": "Fabien Potencier",
"email": "fabien@symfony.com"
},
{
"name": "Symfony Community",
"homepage": "https://symfony.com/contributors"
}
],
"description": "Eases the creation of beautiful and testable command line interfaces",
"homepage": "https://symfony.com",
"keywords": [
"cli",
"command-line",
"console",
"terminal"
],
"install-path": "../symfony/console"
},
{
"name": "symfony/deprecation-contracts",
"version": "v3.5.0",
"version_normalized": "3.5.0.0",
"dist": {
"type": "zip",
"url": "https://mirrors.cloud.tencent.com/repository/composer/symfony/deprecation-contracts/v3.5.0/symfony-deprecation-contracts-v3.5.0.zip",
"reference": "0e0d29ce1f20deffb4ab1b016a7257c4f1e789a1",
"shasum": ""
},
"require": {
"php": ">=8.1"
},
"time": "2024-04-18T09:32:20+00:00",
"type": "library",
"extra": {
"branch-alias": {
"dev-main": "3.5-dev"
},
"thanks": {
"name": "symfony/contracts",
"url": "https://github.com/symfony/contracts"
}
},
"installation-source": "dist",
"autoload": {
"files": [
"function.php"
]
},
"license": [
"MIT"
],
"authors": [
{
"name": "Nicolas Grekas",
"email": "p@tchwork.com"
},
{
"name": "Symfony Community",
"homepage": "https://symfony.com/contributors"
}
],
"description": "A generic function and convention to trigger deprecation notices",
"homepage": "https://symfony.com",
"install-path": "../symfony/deprecation-contracts"
},
{
"name": "symfony/polyfill-ctype",
"version": "v1.30.0",
"version_normalized": "1.30.0.0",
"dist": {
"type": "zip",
"url": "https://mirrors.cloud.tencent.com/repository/composer/symfony/polyfill-ctype/v1.30.0/symfony-polyfill-ctype-v1.30.0.zip",
"reference": "0424dff1c58f028c451efff2045f5d92410bd540",
"shasum": ""
},
"require": {
"php": ">=7.1"
},
"provide": {
"ext-ctype": "*"
},
"suggest": {
"ext-ctype": "For best performance"
},
"time": "2024-05-31T15:07:36+00:00",
"type": "library",
"extra": {
"thanks": {
"name": "symfony/polyfill",
"url": "https://github.com/symfony/polyfill"
}
},
"installation-source": "dist",
"autoload": {
"files": [
"bootstrap.php"
],
"psr-4": {
"Symfony\\Polyfill\\Ctype\\": ""
}
},
"license": [
"MIT"
],
"authors": [
{
"name": "Gert de Pagter",
"email": "BackEndTea@gmail.com"
},
{
"name": "Symfony Community",
"homepage": "https://symfony.com/contributors"
}
],
"description": "Symfony polyfill for ctype functions",
"homepage": "https://symfony.com",
"keywords": [
"compatibility",
"ctype",
"polyfill",
"portable"
],
"install-path": "../symfony/polyfill-ctype"
},
{
"name": "symfony/polyfill-intl-grapheme",
"version": "v1.30.0",
"version_normalized": "1.30.0.0",
"dist": {
"type": "zip",
"url": "https://mirrors.cloud.tencent.com/repository/composer/symfony/polyfill-intl-grapheme/v1.30.0/symfony-polyfill-intl-grapheme-v1.30.0.zip",
"reference": "64647a7c30b2283f5d49b874d84a18fc22054b7a",
"shasum": ""
},
"require": {
"php": ">=7.1"
},
"suggest": {
"ext-intl": "For best performance"
},
"time": "2024-05-31T15:07:36+00:00",
"type": "library",
"extra": {
"thanks": {
"name": "symfony/polyfill",
"url": "https://github.com/symfony/polyfill"
}
},
"installation-source": "dist",
"autoload": {
"files": [
"bootstrap.php"
],
"psr-4": {
"Symfony\\Polyfill\\Intl\\Grapheme\\": ""
}
},
"license": [
"MIT"
],
"authors": [
{
"name": "Nicolas Grekas",
"email": "p@tchwork.com"
},
{
"name": "Symfony Community",
"homepage": "https://symfony.com/contributors"
}
],
"description": "Symfony polyfill for intl's grapheme_* functions",
"homepage": "https://symfony.com",
"keywords": [
"compatibility",
"grapheme",
"intl",
"polyfill",
"portable",
"shim"
],
"install-path": "../symfony/polyfill-intl-grapheme"
},
{
"name": "symfony/polyfill-intl-normalizer",
"version": "v1.30.0",
"version_normalized": "1.30.0.0",
"dist": {
"type": "zip",
"url": "https://mirrors.cloud.tencent.com/repository/composer/symfony/polyfill-intl-normalizer/v1.30.0/symfony-polyfill-intl-normalizer-v1.30.0.zip",
"reference": "a95281b0be0d9ab48050ebd988b967875cdb9fdb",
"shasum": ""
},
"require": {
"php": ">=7.1"
},
"suggest": {
"ext-intl": "For best performance"
},
"time": "2024-05-31T15:07:36+00:00",
"type": "library",
"extra": {
"thanks": {
"name": "symfony/polyfill",
"url": "https://github.com/symfony/polyfill"
}
},
"installation-source": "dist",
"autoload": {
"files": [
"bootstrap.php"
],
"psr-4": {
"Symfony\\Polyfill\\Intl\\Normalizer\\": ""
},
"classmap": [
"Resources/stubs"
]
},
"license": [
"MIT"
],
"authors": [
{
"name": "Nicolas Grekas",
"email": "p@tchwork.com"
},
{
"name": "Symfony Community",
"homepage": "https://symfony.com/contributors"
}
],
"description": "Symfony polyfill for intl's Normalizer class and related functions",
"homepage": "https://symfony.com",
"keywords": [
"compatibility",
"intl",
"normalizer",
"polyfill",
"portable",
"shim"
],
"install-path": "../symfony/polyfill-intl-normalizer"
},
{
"name": "symfony/polyfill-mbstring",
"version": "v1.30.0",
"version_normalized": "1.30.0.0",
"dist": {
"type": "zip",
"url": "https://mirrors.cloud.tencent.com/repository/composer/symfony/polyfill-mbstring/v1.30.0/symfony-polyfill-mbstring-v1.30.0.zip",
"reference": "fd22ab50000ef01661e2a31d850ebaa297f8e03c",
"shasum": ""
},
"require": {
"php": ">=7.1"
},
"provide": {
"ext-mbstring": "*"
},
"suggest": {
"ext-mbstring": "For best performance"
},
"time": "2024-06-19T12:30:46+00:00",
"type": "library",
"extra": {
"thanks": {
"name": "symfony/polyfill",
"url": "https://github.com/symfony/polyfill"
}
},
"installation-source": "dist",
"autoload": {
"files": [
"bootstrap.php"
],
"psr-4": {
"Symfony\\Polyfill\\Mbstring\\": ""
}
},
"license": [
"MIT"
],
"authors": [
{
"name": "Nicolas Grekas",
"email": "p@tchwork.com"
},
{
"name": "Symfony Community",
"homepage": "https://symfony.com/contributors"
}
],
"description": "Symfony polyfill for the Mbstring extension",
"homepage": "https://symfony.com",
"keywords": [
"compatibility",
"mbstring",
"polyfill",
"portable",
"shim"
],
"install-path": "../symfony/polyfill-mbstring"
},
{
"name": "symfony/process",
"version": "v6.4.8",
"version_normalized": "6.4.8.0",
"dist": {
"type": "zip",
"url": "https://mirrors.cloud.tencent.com/repository/composer/symfony/process/v6.4.8/symfony-process-v6.4.8.zip",
"reference": "8d92dd79149f29e89ee0f480254db595f6a6a2c5",
"shasum": ""
},
"require": {
"php": ">=8.1"
},
"time": "2024-05-31T14:49:08+00:00",
"type": "library",
"installation-source": "dist",
"autoload": {
"psr-4": {
"Symfony\\Component\\Process\\": ""
},
"exclude-from-classmap": [
"/Tests/"
]
},
"license": [
"MIT"
],
"authors": [
{
"name": "Fabien Potencier",
"email": "fabien@symfony.com"
},
{
"name": "Symfony Community",
"homepage": "https://symfony.com/contributors"
}
],
"description": "Executes commands in sub-processes",
"homepage": "https://symfony.com",
"install-path": "../symfony/process"
},
{
"name": "symfony/service-contracts",
"version": "v3.5.0",
"version_normalized": "3.5.0.0",
"dist": {
"type": "zip",
"url": "https://mirrors.cloud.tencent.com/repository/composer/symfony/service-contracts/v3.5.0/symfony-service-contracts-v3.5.0.zip",
"reference": "bd1d9e59a81d8fa4acdcea3f617c581f7475a80f",
"shasum": ""
},
"require": {
"php": ">=8.1",
"psr/container": "^1.1|^2.0",
"symfony/deprecation-contracts": "^2.5|^3"
},
"conflict": {
"ext-psr": "<1.1|>=2"
},
"time": "2024-04-18T09:32:20+00:00",
"type": "library",
"extra": {
"branch-alias": {
"dev-main": "3.5-dev"
},
"thanks": {
"name": "symfony/contracts",
"url": "https://github.com/symfony/contracts"
}
},
"installation-source": "dist",
"autoload": {
"psr-4": {
"Symfony\\Contracts\\Service\\": ""
},
"exclude-from-classmap": [
"/Test/"
]
},
"license": [
"MIT"
],
"authors": [
{
"name": "Nicolas Grekas",
"email": "p@tchwork.com"
},
{
"name": "Symfony Community",
"homepage": "https://symfony.com/contributors"
}
],
"description": "Generic abstractions related to writing services",
"homepage": "https://symfony.com",
"keywords": [
"abstractions",
"contracts",
"decoupling",
"interfaces",
"interoperability",
"standards"
],
"install-path": "../symfony/service-contracts"
},
{
"name": "symfony/string",
"version": "v7.1.3",
"version_normalized": "7.1.3.0",
"dist": {
"type": "zip",
"url": "https://mirrors.cloud.tencent.com/repository/composer/symfony/string/v7.1.3/symfony-string-v7.1.3.zip",
"reference": "ea272a882be7f20cad58d5d78c215001617b7f07",
"shasum": ""
},
"require": {
"php": ">=8.2",
"symfony/polyfill-ctype": "~1.8",
"symfony/polyfill-intl-grapheme": "~1.0",
"symfony/polyfill-intl-normalizer": "~1.0",
"symfony/polyfill-mbstring": "~1.0"
},
"conflict": {
"symfony/translation-contracts": "<2.5"
},
"require-dev": {
"symfony/emoji": "^7.1",
"symfony/error-handler": "^6.4|^7.0",
"symfony/http-client": "^6.4|^7.0",
"symfony/intl": "^6.4|^7.0",
"symfony/translation-contracts": "^2.5|^3.0",
"symfony/var-exporter": "^6.4|^7.0"
},
"time": "2024-07-22T10:25:37+00:00",
"type": "library",
"installation-source": "dist",
"autoload": {
"files": [
"Resources/functions.php"
],
"psr-4": {
"Symfony\\Component\\String\\": ""
},
"exclude-from-classmap": [
"/Tests/"
]
},
"license": [
"MIT"
],
"authors": [
{
"name": "Nicolas Grekas",
"email": "p@tchwork.com"
},
{
"name": "Symfony Community",
"homepage": "https://symfony.com/contributors"
}
],
"description": "Provides an object-oriented API to strings and deals with bytes, UTF-8 code points and grapheme clusters in a unified way",
"homepage": "https://symfony.com",
"keywords": [
"grapheme",
"i18n",
"string",
"unicode",
"utf-8",
"utf8"
],
"install-path": "../symfony/string"
}
],
"dev": true,
"dev-package-names": []
}

View File

@@ -0,0 +1,128 @@
<?php return array(
'root' => array(
'name' => '__root__',
'pretty_version' => '1.0.0+no-version-set',
'version' => '1.0.0.0',
'reference' => null,
'type' => 'library',
'install_path' => __DIR__ . '/../../',
'aliases' => array(),
'dev' => true,
),
'versions' => array(
'__root__' => array(
'pretty_version' => '1.0.0+no-version-set',
'version' => '1.0.0.0',
'reference' => null,
'type' => 'library',
'install_path' => __DIR__ . '/../../',
'aliases' => array(),
'dev_requirement' => false,
),
'overtrue/php-opencc' => array(
'pretty_version' => '1.0.0',
'version' => '1.0.0.0',
'reference' => '747e9790ff59f589fca6748497242332553723b3',
'type' => 'library',
'install_path' => __DIR__ . '/../overtrue/php-opencc',
'aliases' => array(),
'dev_requirement' => false,
),
'psr/container' => array(
'pretty_version' => '2.0.2',
'version' => '2.0.2.0',
'reference' => 'c71ecc56dfe541dbd90c5360474fbc405f8d5963',
'type' => 'library',
'install_path' => __DIR__ . '/../psr/container',
'aliases' => array(),
'dev_requirement' => false,
),
'psr/log-implementation' => array(
'dev_requirement' => false,
'provided' => array(
0 => '1.0|2.0|3.0',
),
),
'symfony/console' => array(
'pretty_version' => 'v6.4.10',
'version' => '6.4.10.0',
'reference' => '504974cbe43d05f83b201d6498c206f16fc0cdbc',
'type' => 'library',
'install_path' => __DIR__ . '/../symfony/console',
'aliases' => array(),
'dev_requirement' => false,
),
'symfony/deprecation-contracts' => array(
'pretty_version' => 'v3.5.0',
'version' => '3.5.0.0',
'reference' => '0e0d29ce1f20deffb4ab1b016a7257c4f1e789a1',
'type' => 'library',
'install_path' => __DIR__ . '/../symfony/deprecation-contracts',
'aliases' => array(),
'dev_requirement' => false,
),
'symfony/polyfill-ctype' => array(
'pretty_version' => 'v1.30.0',
'version' => '1.30.0.0',
'reference' => '0424dff1c58f028c451efff2045f5d92410bd540',
'type' => 'library',
'install_path' => __DIR__ . '/../symfony/polyfill-ctype',
'aliases' => array(),
'dev_requirement' => false,
),
'symfony/polyfill-intl-grapheme' => array(
'pretty_version' => 'v1.30.0',
'version' => '1.30.0.0',
'reference' => '64647a7c30b2283f5d49b874d84a18fc22054b7a',
'type' => 'library',
'install_path' => __DIR__ . '/../symfony/polyfill-intl-grapheme',
'aliases' => array(),
'dev_requirement' => false,
),
'symfony/polyfill-intl-normalizer' => array(
'pretty_version' => 'v1.30.0',
'version' => '1.30.0.0',
'reference' => 'a95281b0be0d9ab48050ebd988b967875cdb9fdb',
'type' => 'library',
'install_path' => __DIR__ . '/../symfony/polyfill-intl-normalizer',
'aliases' => array(),
'dev_requirement' => false,
),
'symfony/polyfill-mbstring' => array(
'pretty_version' => 'v1.30.0',
'version' => '1.30.0.0',
'reference' => 'fd22ab50000ef01661e2a31d850ebaa297f8e03c',
'type' => 'library',
'install_path' => __DIR__ . '/../symfony/polyfill-mbstring',
'aliases' => array(),
'dev_requirement' => false,
),
'symfony/process' => array(
'pretty_version' => 'v6.4.8',
'version' => '6.4.8.0',
'reference' => '8d92dd79149f29e89ee0f480254db595f6a6a2c5',
'type' => 'library',
'install_path' => __DIR__ . '/../symfony/process',
'aliases' => array(),
'dev_requirement' => false,
),
'symfony/service-contracts' => array(
'pretty_version' => 'v3.5.0',
'version' => '3.5.0.0',
'reference' => 'bd1d9e59a81d8fa4acdcea3f617c581f7475a80f',
'type' => 'library',
'install_path' => __DIR__ . '/../symfony/service-contracts',
'aliases' => array(),
'dev_requirement' => false,
),
'symfony/string' => array(
'pretty_version' => 'v7.1.3',
'version' => '7.1.3.0',
'reference' => 'ea272a882be7f20cad58d5d78c215001617b7f07',
'type' => 'library',
'install_path' => __DIR__ . '/../symfony/string',
'aliases' => array(),
'dev_requirement' => false,
),
),
);

View File

@@ -0,0 +1,26 @@
<?php
// platform_check.php @generated by Composer
$issues = array();
if (!(PHP_VERSION_ID >= 70000)) {
$issues[] = 'Your Composer dependencies require a PHP version ">= 7.0.0". You are running ' . PHP_VERSION . '.';
}
if ($issues) {
if (!headers_sent()) {
header('HTTP/1.1 500 Internal Server Error');
}
if (!ini_get('display_errors')) {
if (PHP_SAPI === 'cli' || PHP_SAPI === 'phpdbg') {
fwrite(STDERR, 'Composer detected issues in your platform:' . PHP_EOL.PHP_EOL . implode(PHP_EOL, $issues) . PHP_EOL.PHP_EOL);
} elseif (!headers_sent()) {
echo 'Composer detected issues in your platform:' . PHP_EOL.PHP_EOL . str_replace('You are running '.PHP_VERSION.'.', '', implode(PHP_EOL, $issues)) . PHP_EOL.PHP_EOL;
}
}
trigger_error(
'Composer detected issues in your platform: ' . implode(' ', $issues),
E_USER_ERROR
);
}

View File

@@ -0,0 +1,20 @@
root = true
[*]
indent_style = space
indent_size = 4
end_of_line = lf
charset = utf-8
trim_trailing_whitespace = true
insert_final_newline = false
[*.{vue,js,scss}]
charset = utf-8
indent_style = space
indent_size = 2
end_of_line = lf
insert_final_newline = true
trim_trailing_whitespace = true
[*.md]
trim_trailing_whitespace = false

View File

@@ -0,0 +1 @@
github: [overtrue]

View File

@@ -0,0 +1,37 @@
name: Test
on:
push:
branches: [master]
pull_request:
branches: [master]
jobs:
phpcs:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- name: Setup PHP environment
uses: shivammathur/setup-php@v2
with:
php-version: 8.1
- name: Install dependencies
run: composer install
- name: pint check
run: composer check-style
phpunit:
strategy:
matrix:
php_version: [8.0, 8.1, 8.2]
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- name: Setup PHP environment
uses: shivammathur/setup-php@v2
with:
php-version: ${{ matrix.php_version }}
coverage: xdebug
- name: Install dependencies
run: composer install
- name: PHPUnit check
run: ./vendor/bin/phpunit --coverage-text

View File

@@ -0,0 +1,21 @@
MIT License
Copyright (c) 2022 overtrue
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

View File

@@ -0,0 +1,113 @@
# PHP OpenCC
中文简繁转换,支持词汇级别的转换、异体字转换和地区习惯用词转换(中国大陆、台湾、香港、日本新字体)。基于 [BYVoid/OpenCC](https://github.com/BYVoid/OpenCC) 数据实现。
[![Build Status](https://github.com/overtrue/php-opencc/actions/workflows/test.yml/badge.svg)](https://github.com/overtrue/php-opencc/actions/workflows/test.yml)
[![Latest Stable Version](https://poser.pugx.org/overtrue/php-opencc/v/stable)](https://packagist.org/packages/overtrue/php-opencc)
[![Total Downloads](https://poser.pugx.org/overtrue/php-opencc/downloads)](https://packagist.org/packages/overtrue/php-opencc)
[![License](https://poser.pugx.org/overtrue/php-opencc/license)](https://packagist.org/packages/overtrue/php-opencc)
## 安装
```shell
$ composer require overtrue/php-opencc -vvv
```
## 使用
```php
use Overtrue\OpenCC\OpenCC;
echo OpenCC::convert('服务器', 'SIMPLIFIED_TO_TAIWAN_WITH_PHRASE');
// output: 伺服器
```
### 使用策略别名
```php
use Overtrue\OpenCC\OpenCC;
use Overtrue\OpenCC\Strategy;
// 以下方法等价:
// 方法
echo OpenCC::s2tw('服务器');
echo OpenCC::simplifiedToTaiwan('服务器');
// 字符串
echo OpenCC::convert('服务器', 's2tw');
echo OpenCC::convert('服务器', 'S2TW');
echo OpenCC::convert('服务器', 'SIMPLIFIED_TO_TAIWAN');
// 常量
echo OpenCC::convert('服务器', Strategy::S2TW);
echo OpenCC::convert('服务器', Strategy::SIMPLIFIED_TO_TAIWAN);
```
### 转换策略
| 策略 (别名) | 说明 |
|-------------------------------------------|-----------------|
| `SIMPLIFIED_TO_TRADITIONAL(S2T)` | 简体到繁体 |
| `SIMPLIFIED_TO_HONGKONG(S2HK)` | 简体到香港繁体 |
| `SIMPLIFIED_TO_JAPANESE(S2JP)` | 简体到日文 |
| `SIMPLIFIED_TO_TAIWAN(S2TW)` | 简体到台湾正体 |
| `SIMPLIFIED_TO_TAIWAN_WITH_PHRASE(2TWP)` | 简体到台湾正体, 带词汇本地化 |
| `HONGKONG_TO_TRADITIONAL(HK2T)` | 香港繁体到正体 |
| `HONGKONG_TO_SIMPLIFIED(HK2S)` | 香港繁体到简体 |
| `TAIWAN_TO_SIMPLIFIED(TW2S)` | 台湾正体到简体 |
| `TAIWAN_TO_TRADITIONAL(TW2T)` | 台湾正体到繁体 |
| `TAIWAN_TO_SIMPLIFIED_WITH_PHRASE(TW2SP)` | 台湾正体到简体, 带词汇本地化 |
| `TRADITIONAL_TO_HONGKONG(T2HK)` | 正体到香港繁体 |
| `TRADITIONAL_TO_SIMPLIFIED(T2S)` | 繁体到简体 |
| `TRADITIONAL_TO_TAIWAN(T2TW)` | 繁体到台湾正体 |
| `TRADITIONAL_TO_JAPANESE(T2JP)` | 繁体到日文 |
| `JAPANESE_TO_TRADITIONAL(JP2T)` | 日文到繁体 |
| `JAPANESE_TO_SIMPLIFIED(JP2S)` | 日文到简体 |
### 在命令行使用
```shell
$ php vendor/bin/opencc "汉字" s2tw
```
说明:
```bash
$ php vendor/bin/opencc --help
Description:
中文简繁转换,支持词汇级别的转换、异体字转换和地区习惯用词转换(中国大陆、台湾、香港、日本新字体)。
Usage:
convert <string> [<strategy>]
Arguments:
string 待转换的字符串
strategy 转换策略 [default: "SIMPLIFIED_TO_TRADITIONAL"]
```
## :heart: 赞助我
如果你喜欢我的项目并想支持它,[点击这里 :heart:](https://github.com/sponsors/overtrue)
## Project supported by JetBrains
Many thanks to Jetbrains for kindly providing a license for me to work on this and other open-source projects.
[![](https://resources.jetbrains.com/storage/products/company/brand/logos/jb_beam.svg)](https://www.jetbrains.com/?from=https://github.com/overtrue)
## 参与贡献
You can contribute in one of three ways:
1. File bug reports using the [issue tracker](https://github.com/overtrue/php-opencc/issues).
2. Answer questions or fix bugs on the [issue tracker](https://github.com/overtrue/php-opencc/issues).
3. Contribute new features or update the wiki.
_The code contribution process is not very formal. You just need to make sure that you follow the PSR-0, PSR-1, and PSR-2 coding guidelines. Any new code contributions must be accompanied by unit tests where applicable._
## License
MIT

View File

@@ -0,0 +1,13 @@
#!/usr/bin/env php
<?php
include $_composer_autoload_path ?? __DIR__ . '/../vendor/autoload.php';
use Overtrue\PHPOpenCC\Console\BuildCommand;
use Symfony\Component\Console\Application;
$application = new Application("PHP OpenCC by @overtrue" );
$application->add(new BuildCommand());
$application->setDefaultCommand(BuildCommand::getDefaultName(), true);
$application->run();

View File

@@ -0,0 +1,14 @@
#!/usr/bin/env php
<?php
include $_composer_autoload_path ?? __DIR__ . '/../vendor/autoload.php';
use Overtrue\PHPOpenCC\Console\BuildCommand;
use Overtrue\PHPOpenCC\Console\ConvertCommand;
use Symfony\Component\Console\Application;
$application = new Application("PHP OpenCC by @overtrue" );
$application->add(new ConvertCommand());
$application->setDefaultCommand(ConvertCommand::getDefaultName(), true);
$application->run();

View File

@@ -0,0 +1,70 @@
{
"name": "overtrue/php-opencc",
"description": "中文简繁转换,支持词汇级别的转换、异体字转换和地区习惯用词转换(中国大陆、台湾、香港、日本新字体)。基于 [BYVoid/OpenCC](https://github.com/BYVoid/OpenCC) 数据实现。",
"license": "MIT",
"authors": [
{
"name": "overtrue",
"email": "i@overtrue.me"
}
],
"require": {
"php": ">=8.0",
"ext-zip": "*",
"symfony/console": "^5.4|^6.3",
"symfony/process": "^5.4|^6.3"
},
"require-dev": {
"brainmaestro/composer-git-hooks": "dev-master",
"mockery/mockery": "^1.2",
"phpunit/phpunit": "^9.0",
"vimeo/psalm": "^4.10",
"jetbrains/phpstorm-attributes": "^1.0",
"laravel/pint": "^0.1|^1.10"
},
"bin": [
"bin/opencc"
],
"autoload": {
"psr-4": {
"Overtrue\\PHPOpenCC\\": "src"
}
},
"extra": {
"hooks": {
"pre-commit": [
"composer pint",
"composer test"
],
"pre-push": [
"composer pint",
"composer test"
]
}
},
"scripts": {
"post-update-cmd": [
"cghooks remove",
"cghooks add --ignore-lock",
"cghooks update"
],
"post-merge": "composer install",
"post-install-cmd": [
"cghooks remove",
"cghooks add --ignore-lock",
"cghooks update"
],
"cghooks": "vendor/bin/cghooks",
"check-style": "vendor/bin/pint ./src ./tests --test",
"pint": "vendor/bin/pint ./src ./tests",
"fix-style": "vendor/bin/pint ./src ./tests",
"test": "phpunit --colors",
"psalm": "psalm --show-info=true --no-cache",
"psalm-fix": "psalm --no-cache --alter --issues=MissingReturnType,MissingParamType"
},
"scripts-descriptions": {
"test": "Run all tests.",
"check-style": "Run style checks (only dry run - no fixing!).",
"fix-style": "Run style checks and fix violations."
}
}

View File

@@ -0,0 +1,63 @@
僞 偽
兌 兑
叄 叁
只 只 衹
啓 啓 啟
喫 吃
囪 囱
妝 妝 粧
媼 媪
嬀 媯
悅 悦
慍 愠
戶 户
挩 捝
搵 揾
擡 抬
敓 敚
敘 敍 敘
柺 枴
梲 棁
棱 稜 棱
榲 榅
檯 枱
氳 氲
涗 涚
溫 温
溼 濕
潙 溈
潨 潀
熅 煴
爲 為
癡 痴
皁 皂
祕 秘
稅 税
竈 灶
糉 粽 糉 糭
縕 緼
纔 才
脣 唇
脫 脱
膃 腽
臥 卧
臺 台
菸 煙
蒕 蒀
蔥 葱
蔿 蒍
蘊 藴
蛻 蜕
衆 眾
衛 衞
覈 核
說 説
踊 踴
轀 輼
醞 醖
鉢 缽
鉤 鈎
銳 鋭
鍼 針
閱 閲
鰮 鰛

View File

@@ -0,0 +1,156 @@
一口吃個 一口喫個
一口吃成 一口喫成
一家三口 一家三口
一家五口 一家五口
一家六口 一家六口
一家四口 一家四口
七星巖 七星巖
世胄 世胄
介胄 介冑
傅巖 傅巖
免胄 免冑
冠胄 冠冑
千巖競秀 千巖競秀
千巖萬壑 千巖萬壑
千巖萬谷 千巖萬谷
口吃 口吃
台山 台山
台州 台州
台州地區 台州地區
台州市 台州市
吃口 喫口 吃口
吃口令 吃口令
吃口飯 喫口飯
吃吃 喫喫 吃吃
吃子 喫子 吃子
名胄 名胄
國胄 國胄
圍巖 圍巖
地胄 地胄
壓胄子 壓冑子
士胄 士胄
大巖桐 大巖桐
天台女 天台女
天台宗 天台宗
天台山 天台山
天台縣 天台縣
天潢貴胄 天潢貴胄
奇巖 奇巖
寶胄 寶胄
小巖洞 小巖洞
岫巖縣 岫巖縣
峯巖 峯巖
嵌巖 嵌巖
巉巖 巉巖
巖壁 巖壁
巖居 巖居
巖居穴處 巖居穴處
巖居谷飲 巖居谷飲
巖岸 巖岸
巖巉 巖巉
巖巖 巖巖
巖徼 巖徼
巖手縣 巖手縣
巖村 巖村
巖洞 巖洞
巖流圈 巖流圈
巖牆 巖牆
巖牆之下 巖牆之下
巖畫 巖畫
巖穴 巖穴
巖穴之士 巖穴之士
巖薔薇 巖薔薇
巖邑 巖邑
巖郎 巖郎
巖阻 巖阻
巖陛 巖陛
帝胄 帝胄
幽巖 幽巖
幽棲巖谷 幽棲巖谷
張口 張口
懸巖 懸巖
懸巖峭壁 懸巖峭壁
懸胄 懸冑
攀巖 攀巖
支胄 支胄
教胄 教胄
景胄 景胄
望胄 望胄
末胄 末胄
村胄 村胄
枕巖漱流 枕巖漱流
枝胄 枝胄
氏胄 氏胄
洪胄 洪胄
浙江天台縣 浙江天台縣
清胄 清胄
灰巖殘丘 灰巖殘丘
玄胄 玄胄
甲胄 甲冑
甲胄魚類 甲冑魚類
皇胄 皇胄
石灰巖洞 石灰巖洞
神胄 神胄
簪纓世胄 簪纓世胄
系胄 系胄
紅巖 紅巖
絕巖 絕巖
緒胄 緒胄
纂胄 纂胄
胃口 胃口
胄嗣 胄嗣
胄子 胄子
胄序 胄序
胄族 胄族
胄甲 冑甲
胄監 胄監
胄科 冑科
胄緒 胄緒
胄胤 胄胤
胄裔 胄裔
胄裔繁衍 胄裔繁衍
胄閥 胄閥
胡雪巖 胡雪巖
胤胄 胤胄
苗胄 苗胄
英胄 英胄
華胄 華胄
血胄 血胄
裔胄 裔胄
訓胄 訓胄
試胄 試胄
豪門貴胄 豪門貴胄
貝胄 貝冑
貴胄 貴胄
賢胄 賢胄
蹇吃 蹇吃
躬擐甲胄 躬擐甲冑
遐胄 遐胄
遙胄 遙胄
遙遙華胄 遙遙華胄
遠胄 遠胄
遺胄 遺胄
鄧艾吃 鄧艾吃
重巖疊嶂 重巖疊嶂
金胄 金胄
鎧胄 鎧冑
鑿巖 鑿巖
門胄 門胄
開口 開口
雲巖區 雲巖區
非層巖 非層巖
韓侂胄 韓侂冑
飮胄 飮冑
骨巖巖 骨巖巖
高胄 高胄
魚胄 魚冑
鮮胄 鮮胄
鴻胄 鴻胄
黃巖區 黃巖區
黃巖島 黃巖島
黃炎貴胄 黃炎貴胄
齒胄 齒胄
龍巖 龍巖
龍巖市 龍巖市
龍巖村 龍巖村
龍胄 龍胄

View File

@@ -0,0 +1,7 @@
両 兩 輛
弁 辨 辯 瓣 辦 弁
御 御 禦
欠 缺 欠
糸 絲 糸
芸 藝 芸
浜 濱 浜

View File

@@ -0,0 +1,176 @@
一獲千金 一攫千金
丁寧 叮嚀
丁重 鄭重
三差路 三叉路
世論 輿論
亜鈴 啞鈴
交差 交叉
供宴 饗宴
俊馬 駿馬
保塁 堡壘
個条書 箇条書
偏平 扁平
停泊 碇泊
優俊 優駿
先兵 尖兵
先鋭 尖鋭
共役 共軛
冗舌 饒舌
凶器 兇器
削岩 鑿岩
包丁 庖丁
包帯 繃帯
区画 區劃
厳然 儼然
友宜 友誼
反乱 叛乱
収集 蒐集
叙情 抒情
台頭 擡頭
合弁 合辦
喜遊曲 嬉遊曲
嘆願 歎願
回転 廻転
回遊 回游
奉持 捧持
委縮 萎縮
展転 輾轉
希少 稀少
幻惑 眩惑
広範 廣汎
広野 曠野
廃虚 廢墟
建坪率 建蔽率
弁当 辨當
弁膜 瓣膜
弁護 辯護
弁髪 辮髮
弦歌 絃歌
恩義 恩誼
意向 意嚮
慰謝料 慰藉料
憶断 臆断
憶病 臆病
戦没 戰歿
扇情 煽情
手帳 手帖
技量 伎倆
抜粋 抜萃
披歴 披瀝
抵触 牴触
抽選 抽籤
拘引 勾引
拠出 醵出
拠金 醵金
掘削 掘鑿
控除 扣除
援護 掩護
放棄 抛棄
散水 撒水
敬謙 敬虔
敷延 敷衍
断固 断乎
族生 簇生
昇叙 陞敘
暖房 煖房
暗唱 暗誦
暗夜 闇夜
暴露 曝露
枯渇 涸渇
格好 恰好
格幅 恰幅
棄損 毀損
模索 摸索
橋頭保 橋頭堡
欠缺 欠缺
死体 屍體
殿部 臀部
母指 拇指
気迫 気魄
決別 訣別
決壊 決潰
沈殿 沈澱
油送船 油槽船
波乱 波瀾
注釈 註釋
洗浄 洗滌 洗浄
活発 活潑
浸透 滲透
浸食 浸蝕
消却 銷卻
混然 渾然
湾曲 彎曲
溶接 熔接
漁労 漁撈
漂然 飄然
激高 激昂
火炎 火焰
焦燥 焦躁
班点 斑点
留飲 溜飲
略奪 掠奪
疎通 疏通
発酵 醱酵
白亜 白堊
相克 相剋
知恵 智慧
破棄 破毀
確固 確乎
禁固 禁錮
符丁 符牒
粉装 扮装
紫班 紫斑
終息 終熄
総合 綜合
編集 編輯
義援 義捐
耕運機 耕耘機
肝心 肝腎
肩甲骨 肩胛骨
背徳 悖德
脈拍 脈搏
膨張 膨脹
芳純 芳醇
英知 叡智
蒸留 蒸溜
薫蒸 燻蒸
薫製 燻製
衣装 衣裳
衰退 衰退 衰頽
裕然 悠然
補佐 輔佐
訓戒 訓誡
試練 試煉
詭弁 詭辯
講和 媾和
象眼 象嵌
貫録 貫禄
買弁 買辦
賛辞 讚辭
踏襲 蹈襲
車両 車輛
転倒 顛倒
輪郭 輪廓
退色 褪色
途絶 杜絶
連係 連繫
連合 聯合
選考 銓衡
酢酸 醋酸
野卑 野鄙
鉱石 礦石
間欠 間歇
関数 函數
防御 防禦
険阻 嶮岨
障壁 牆壁
障害 障礙
隠滅 湮滅
集落 聚落
雇用 雇傭
風諭 諷喩
飛語 蜚語
香典 香奠
骨格 骨骼
高進 亢進
鳥観 鳥瞰

View File

@@ -0,0 +1,367 @@
乘 乗
亂 乱
亙 亘
亞 亜
佛 仏
來 来
假 仮
傳 伝
僞 偽
價 価
儉 倹
兒 児
內 内
兩 両
剎 刹
剩 剰
劍 剣
劑 剤
勞 労
勳 勲
勵 励
勸 勧
勻 匀
區 区
卷 巻
卻 却
參 参
吳 呉
咒 呪
啞 唖
單 単
噓 嘘
嚙 噛
嚴 厳
囑 嘱
圈 圏
國 国
圍 囲
圓 円
圖 図
團 団
增 増
墮 堕
壓 圧
壘 塁
壞 壊
壤 壌
壯 壮
壹 壱
壽 寿
奧 奥
奬 奨
妝 粧
孃 嬢
學 学
寢 寝
實 実
寫 写
寬 寛
寶 宝
將 将
專 専
對 対
屆 届
屬 属
峯 峰
峽 峡
嶽 岳
巖 巌
巢 巣
帶 帯
廁 厠
廢 廃
廣 広
廳 庁
彈 弾
彌 弥
彎 弯
彥 彦
徑 径
從 従
徵 徴
德 徳
恆 恒
悅 悦
惠 恵
惡 悪
惱 悩
慘 惨
應 応
懷 懐
戀 恋
戰 戦
戲 戯
戶 戸
戾 戻
拂 払
拔 抜
拜 拝
挾 挟
插 挿
揭 掲
搔 掻
搖 揺
搜 捜
摑 掴
擇 択
擊 撃
擔 担
據 拠
擴 拡
攝 摂
攪 撹
收 収
效 効
敕 勅
敘 叙
數 数
斷 断
晉 晋
晚 晩
晝 昼
暨 曁
曆 暦
曉 暁
曾 曽
會 会
枡 桝
查 査
條 条
棧 桟
棱 稜 棱
榆 楡
榮 栄
樂 楽
樓 楼
樞 枢
樣 様
橫 横
檢 検
櫻 桜
權 権
歐 欧
歡 歓
步 歩
歲 歳
歷 歴
歸 帰
殘 残
殼 殻
毆 殴
每 毎
氣 気
污 汚
沒 没
涉 渉
淚 涙
淨 浄
淺 浅
渴 渇
潑 溌
溪 渓
溫 温
溼 湿
滯 滞
滿 満
潛 潜
澀 渋
澤 沢
濟 済
濤 涛
濱 浜
濾 沪
瀧 滝
瀨 瀬
灣 湾
焰 焔
燈 灯
燒 焼
營 営
爐 炉
爭 争
爲 為
牀 床
犧 犠
狀 状
狹 狭
獨 独
獵 猟
獸 獣
獻 献
瓣 弁
產 産
畫 画
當 当
疊 畳
疎 疏
痹 痺
瘦 痩
癡 痴
發 発
皋 皐
盜 盗
盡 尽
碎 砕
祕 秘
祿 禄
禦 御
禪 禅
禮 礼
禱 祷
稅 税
稱 称
稻 稲
穎 頴
穗 穂
穩 穏
穰 穣
竈 竃
竊 窃
粹 粋
糉 粽
絕 絶
絲 糸
經 経
綠 緑
緖 緒
緣 縁
縣 県
縱 縦
總 総
繫 繋
繡 繍
繩 縄
繪 絵
繼 継
續 続
纔 才
纖 繊
缺 欠
罐 缶
羣 群
聯 連
聰 聡
聲 声
聽 聴
肅 粛
脣 唇
脫 脱
腦 脳
腳 脚
膽 胆
臟 臓
臺 台
與 与
舉 挙
舊 旧
舍 舎
荔 茘
莊 荘
莖 茎
菸 煙
萊 莱
萬 万
蔣 蒋
蔥 葱
薰 薫
藏 蔵
藝 芸
藥 薬
蘆 芦
處 処
虛 虚
號 号
螢 蛍
蟲 虫
蠟 蝋
蠶 蚕
蠻 蛮
裝 装
覺 覚
覽 覧
觀 観
觸 触
說 説
謠 謡
證 証
譯 訳
譽 誉
讀 読
變 変
讓 譲
豐 豊
豫 予
貓 猫
貳 弐
賣 売
賴 頼
贊 賛
贗 贋
踐 践
輕 軽
輛 輌
轉 転
辨 弁
辭 辞
辯 弁
遞 逓
遥 遙
遲 遅
邊 辺
鄉 郷
酢 醋
醉 酔
醱 醗
醫 医
醬 醤
釀 醸
釋 釈
鋪 舗
錄 録
錢 銭
鍊 錬
鐵 鉄
鑄 鋳
鑛 鉱
閱 閲
關 関
陷 陥
隨 随
險 険
隱 隠
雙 双
雜 雑
雞 鶏
霸 覇
靈 霊
靜 静
顏 顔
顯 顕
餘 余
騷 騒
驅 駆
驗 験
驛 駅
髓 髄
體 体
髮 髪
鬥 闘
鱉 鼈
鷗 鴎
鹼 鹸
鹽 塩
麥 麦
麪 麺
麴 麹
黃 黄
黑 黒
默 黙
點 点
黨 党
齊 斉
齋 斎
齒 歯
齡 齢
龍 竜
龜 亀

View File

@@ -0,0 +1,13 @@
# OpenCC 数据字典
本目录包含了 [OpenCC](https://github.com/BYVoid/OpenCC) 的数据字典,用于中文简繁转换。
## 数据来源
```
https://github.com/BYVoid/OpenCC/tree/master/data/dictionary
```
# LICENSE
[Apache License 2.0](https://github.com/BYVoid/OpenCC/blob/master/LICENSE)

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,277 @@
一目瞭然 一目了然
上鍊 上链
不瞭解 不了解
么麼 幺麽
么麽 幺麽
乾乾淨淨 干干净净
乾乾脆脆 干干脆脆
乾元 乾元
乾卦 乾卦
乾嘉 乾嘉
乾圖 乾图
乾坤 乾坤
乾坤一擲 乾坤一掷
乾坤再造 乾坤再造
乾坤大挪移 乾坤大挪移
乾宅 乾宅
乾斷 乾断
乾旦 乾旦
乾曜 乾曜
乾清宮 乾清宫
乾盛世 乾盛世
乾紅 乾红
乾綱 乾纲
乾縣 乾县
乾象 乾象
乾造 乾造
乾道 乾道
乾陵 乾陵
乾隆 乾隆
乾隆年間 乾隆年间
乾隆皇帝 乾隆皇帝
二噁英 二𫫇英
以免藉口 以免借口
以功覆過 以功复过
侔德覆載 侔德复载
傢俱 家具
傷亡枕藉 伤亡枕藉
八濛山 八濛山
凌藉 凌借
出醜狼藉 出丑狼藉
函覆 函复
千鍾粟 千锺粟
反反覆覆 反反复复
反覆 反复
反覆思維 反复思维
反覆思量 反复思量
反覆性 反复性
名覆金甌 名复金瓯
哪吒 哪吒
回覆 回复
壺裏乾坤 壶里乾坤
大目乾連冥間救母變文 大目乾连冥间救母变文
宫商角徵羽 宫商角徵羽
射覆 射复
尼乾陀 尼乾陀
幺麼 幺麽
幺麼小丑 幺麽小丑
幺麼小醜 幺麽小丑
康乾 康乾
張法乾 张法乾
彷彿 仿佛
彷徨 彷徨
徵弦 徵弦
徵絃 徵弦
徵羽摩柯 徵羽摩柯
徵聲 徵声
徵調 徵调
徵音 徵音
情有獨鍾 情有独钟 情有独锺
憑藉 凭借
憑藉着 凭借着
手鍊 手链
扭轉乾坤 扭转乾坤
找藉口 找借口
拉鍊 拉链
拉鍊工程 拉链工程
拜覆 拜复
據瞭解 据了解
文錦覆阱 文锦复阱
於世成 於世成
於乎 於乎
於仲完 於仲完
於倫 於伦
於其一 於其一
於則 於则
於勇明 於勇明
於呼哀哉 於呼哀哉
於單 於单
於坦 於坦
於崇文 於崇文
於忠祥 於忠祥
於惟一 於惟一
於戲 於戏
於敖 於敖
於梨華 於梨华
於清言 於清言
於潛 於潜
於琳 於琳
於穆 於穆
於竹屋 於竹屋
於菟 於菟
於邑 於邑
於陵子 於陵子
旋乾轉坤 旋乾转坤
旋轉乾坤 旋转乾坤
旋轉乾坤之力 旋转乾坤之力
明瞭 明了
明覆 明复
書中自有千鍾粟 书中自有千锺粟
有序 有序
朝乾夕惕 朝乾夕惕
木吒 木吒
李乾德 李乾德
李澤鉅 李泽钜
李鍊福 李链福
李鍾郁 李锺郁
樊於期 樊於期
沈沒 沉没
沈沒成本 沉没成本
沈積 沉积
沈船 沉船
沈默 沉默
流徵 流徵
浪蕩乾坤 浪荡乾坤
滑藉 滑借
無序 无序
牴牾 抵牾
牴觸 抵触
狐藉虎威 狐借虎威
珍珠項鍊 珍珠项链
甚鉅 甚钜
申覆 申复
畢昇 毕昇
發覆 发复
瞭如 了如
瞭如指掌 了如指掌
瞭望 瞭望
瞭然 了然
瞭然於心 了然于心
瞭若指掌 了若指掌
瞭解 了解
瞭解到 了解到
示覆 示复
神祇 神祇
稟覆 禀复
竺乾 竺乾
答覆 答复
篤麼 笃麽
簡單明瞭 简单明了
籌畫 筹划
素藉 素借
老態龍鍾 老态龙钟 老态龙锺
肘手鍊足 肘手链足
茵藉 茵借
萬鍾 万锺
蒜薹 蒜薹
蕓薹 芸薹
蕩覆 荡复
蕭乾 萧乾
藉代 借代
藉以 借以
藉助 借助
藉助於 借助于
藉卉 借卉
藉口 借口
藉喻 借喻
藉寇兵 借寇兵
藉寇兵齎盜糧 借寇兵赍盗粮
藉手 借手
藉據 借据
藉故 借故
藉故推辭 借故推辞
藉方 借方
藉條 借条
藉槁 借槁
藉機 借机
藉此 借此
藉此機會 借此机会
藉甚 借甚
藉由 借由
藉着 借着
藉端 借端
藉端生事 借端生事
藉箸代籌 借箸代筹
藉草枕塊 借草枕块
藉藉 藉藉
藉藉无名 藉藉无名
藉詞 借词
藉讀 借读
藉資 借资
衹得 只得
衹見樹木 只见树木
衹見樹木不見森林 只见树木不见森林
袖裏乾坤 袖里乾坤
覆上 复上
覆住 复住
覆信 复信
覆冒 复冒
覆呈 复呈
覆命 复命
覆墓 复墓
覆宗 复宗
覆帳 复帐
覆幬 复帱
覆成 复成
覆按 复按
覆文 复文
覆杯 复杯
覆校 复校
覆瓿 复瓿
覆盂 复盂
覆盆 覆盆
覆盆子 覆盆子
覆盤 覆盘
覆育 复育
覆蕉尋鹿 复蕉寻鹿
覆逆 复逆
覆醢 复醢
覆醬瓿 复酱瓿
覆電 复电
覆露 复露
覆鹿尋蕉 复鹿寻蕉
覆鹿遺蕉 复鹿遗蕉
覆鼎 复鼎
見覆 见复
角徵 角徵
角徵羽 角徵羽
計畫 计划
變徵 变徵
變徵之聲 变徵之声
變徵之音 变徵之音
貂覆額 貂复额
買臣覆水 买臣复水
踅門瞭戶 踅门了户
躪藉 躏借
郭子乾 郭子乾
酒逢知己千鍾少 酒逢知己千锺少
酒逢知己千鍾少話不投機半句多 酒逢知己千锺少话不投机半句多
醞藉 酝借
重覆 重复
金吒 金吒
金鍊 金链
鈞覆 钧复
鉅子 钜子
鉅萬 钜万
鉅防 钜防
鉸鍊 铰链
銀鍊 银链
錢鍾書 钱锺书
鍊墜 链坠
鍊子 链子
鍊形 链形
鍊條 链条
鍊錘 链锤
鍊鎖 链锁
鍛鍾 锻锺
鍾繇 钟繇 锺繇
鍾萬梅 锺万梅
鍾重發 锺重发
鍾鍛 锺锻
鍾馗 锺馗
鎖鍊 锁链
鐵鍊 铁链
鑽石項鍊 钻石项链
雁杳魚沈 雁杳鱼沉
雖覆能復 虽覆能复
電覆 电复
露覆 露复
項鍊 项链
頗覆 颇复
頸鍊 颈链
顛乾倒坤 颠乾倒坤
顛倒乾坤 颠倒乾坤
顧藉 顾借
麼些族 麽些族
黄鍾公 黄锺公
龍鍾 龙钟 龙锺

View File

@@ -0,0 +1,388 @@
PN結 PN接面
SQL注入 SQL隱碼攻擊
SQL注入攻擊 SQL隱碼攻擊
U盤 隨身碟
三極管 三極體
下拉列表 下拉選單
並行計算 平行計算
中間件 中介軟體
串口 串列埠
串行 序列
串行端口 串列埠
主引導記錄 主開機記錄
主板 主機板
二極管 二極體
互聯網 網際網路
交互 互動
交互式 互動式
人工智能 人工智慧
代碼 程式碼 代碼
代碼頁 內碼表
以太網 乙太網
任務欄 工作列
任務管理器 工作管理員
仿真 模擬
位圖 點陣圖
低級 低階 低級
便攜式 行動式 攜帶型
保存 儲存
信噪比 訊雜比
信息 資訊
信息安全 資訊保安
信息技術 資訊科技
信息論 資訊理論
信號 訊號 信號
信道 通道
傳感 感測
像素 畫素
僞代碼 虛擬碼
優先級 優先順序
優化 最佳化
元數據 後設資料
元編程 超程式設計
光標 游標
光盤 光碟
光驅 光碟機
免提 擴音
內存 記憶體
內核 核心
內置 內建
內聯函數 行內函數
全局 全域性
全角 全形
兼容 相容
冒泡排序 氣泡排序
函數 函式
函數式編程 函數語言程式設計
刀片服務器 刀鋒伺服器
分佈式 分散式
分區 分割槽
分辨率 解析度
刷新 重新整理
刻錄 燒錄
前綴 字首
剪切 剪下
剪貼板 剪貼簿
創建 建立
加載 載入
半角 半形
博客 部落格
卸載 解除安裝
原代碼 原始碼
參數 引數
參數表 參數列
句柄 控制代碼
可視化 視覺化
呼出 撥出
呼叫轉移 來電轉駁
命令式編程 指令式程式設計
命令行 命令列
命名空間 名稱空間
哈希 雜湊
單片機 微控制器
回調 回撥
固件 韌體
圖像 影象
圖庫 相簿
圖標 圖示
在線 線上
地址 地址 位址
地址欄 位址列
城域網 都會網路
堆棧 堆疊
場效應管 場效電晶體
壁紙 桌布 壁紙
外置 外接
外鍵 外來鍵
多任務 多工
多態 多型
多線程 多執行緒
字庫 字型檔
字段 欄位
字符 字元
字符串 字串
字符集 字符集
字節 位元組
字體 字型
存儲 儲存
存盤 存檔
宏 宏 巨集
宏內核 單核心
寄存器 暫存器
密鑰 金鑰
實例 例項 實例
實模式 真實模式
審覈 稽覈
寫保護 防寫
寬帶 寬頻
尋址 定址
對話框 對話方塊
對象 物件 對象
導入 匯入
導出 匯出
局域網 區域網
局部 區域性
屏幕 螢幕
屏蔽 遮蔽
嵌套 巢狀
布爾 布林
帶寬 頻寬
引導程序 載入程式
彙編 彙編 組譯
彙編語言 組合語言
後綴 字尾
循環 迴圈 循環
性價比 價效比
性能 效能
截取 擷取
截屏 截圖
打印 列印
打印機 印表機
打開 開啟 打開
批量 批次
拋出 丟擲
拷貝 複製
持久性 永續性
指針 指標
捲積 摺積
掃描儀 掃描器
掛斷 結束通話
採樣 取樣
採樣率 取樣率
接口 介面
控件 控制元件
插件 外掛
搜索 搜尋
操作數 運算元
操作符 運算子
操作系統 作業系統
擴展 擴充套件
擴展名 副檔名
支持 支援
支持者 支持者
散列 雜湊
數字 數字 數位
數字印刷 數位印刷
數字電子 數位電子
數字電路 數位電路
數據 資料
數據倉庫 資料倉儲
數據報 資料包
數據庫 資料庫
數據挖掘 資料探勘
數據源 資料來源
數組 陣列
文件 檔案
文件名 檔名
文件夾 資料夾
文件擴展名 副檔名
文字處理 文書處理
文本 文字
文檔 文件
映射 對映
時分多址 分時多重進接
時分複用 分時多工
時鐘頻率 時脈頻率
晶閘管 閘流體
晶體管 電晶體
智能 智慧
最終用戶 終端使用者
有損壓縮 有失真壓縮
服務器 伺服器
本地代碼 原生代碼
析構函數 解構函式
枚舉 列舉
查找 查詢
查看 檢視
桌面型 桌上型
構造函數 建構函式
標識符 識別符號
模塊 模組
模擬 模擬 類比
模擬電子 類比電子
模擬電路 類比電路
權限 許可權
正則表達式 正規表示式
死機 宕機
殺毒 防毒
比特 位元
比特幣 比特幣
比特率 位元率
波分複用 波長分波多工
消息 訊息 消息
添加 新增
源代碼 原始碼
源文件 原始檔
源碼 原始碼
溢出 溢位
滾動條 捲軸
演示文稿 簡報
激光 鐳射
激活 啟用
無損壓縮 無失真壓縮
物理內存 實體記憶體
物理地址 實體地址
狀態欄 狀態列
用戶 使用者
用戶名 使用者名稱
界面 介面
異步 非同步
登錄 登入
發佈 釋出
發送 傳送
盤片 碟片
盤符 磁碟機代號
目標代碼 目的碼
相冊 相簿
矢量 向量
知識產權 智慧財產權
短信 簡訊
硬件 硬體
硬盤 硬碟
碼分多址 分碼多重進接
碼率 位元速率
磁盤 磁碟
磁道 磁軌
社區 社羣 社區
移動硬盤 行動硬碟
移動網絡 行動網路
移動資料 行動資料
移動通信 行動通訊
移動電話 行動電話
程序 程式
程序員 程式設計師
空分多址 分空間多重進接
空分複用 空間多工
窗口 視窗
端口 埠
筆記本電腦 膝上型電腦
算子 運算元
算法 演算法
範式 正規化
粘貼 貼上 粘貼
紅心大戰 傷心小棧
組件 元件
綁定 繫結
網上鄰居 網路上的芳鄰
網卡 網絡卡
網吧 網咖
網絡 網路
網關 閘道器
線程 執行緒
編程 程式設計
編程語言 程式語言
緩存 快取
縮略圖 縮圖
縮進 縮排
總線 匯流排
缺省 預設
聯繫 聯絡
聯繫歷史 通話記錄
聲卡 音效卡
聲明 宣告
脫機 離線
腳本 指令碼
自動轉屏 自動旋轉螢幕
臺式機 桌上型電腦
航天飛機 太空梭
芯片 晶片
花屏 破圖
菜單 選單 菜單
萬維網 全球資訊網
藍屏 藍色畫面
藍牙 藍芽
虛函數 虛擬函式
虛擬機 虛擬機器
虛擬機器 虛擬機器
表達式 表示式 運算式
複印 影印
複選按鈕 覈取按鈕
複選框 覈取方塊
視圖 檢視
視頻 影片 視訊
視頻會議 視訊會議
視頻通話 視訊通話
解釋器 直譯器
觸摸 觸控
觸摸屏 觸控式螢幕
計算機安全 電腦保安
計算機科學 電腦科學
訪問 訪問 存取
設備 裝置
設置 設定
註冊機 序號產生器
註冊表 登錄檔
註銷 登出
調制 調變
調度 排程
調用 呼叫
調色板 調色盤
調製解調器 數據機
調試 除錯 偵錯
調試器 偵錯程式
變量 變數
軟件 軟體
軟驅 軟碟機
轉義字符 跳脫字元
通信 通訊
通訊卡 通話卡
通配符 萬用字元
連接 連線
連接器 聯結器
進制 進位制
進程 程序 進程
運算符 運算子
運行 執行
過程式編程 程序式程式設計
遞歸 遞迴
遠程 遠端
適配器 介面卡
邏輯門 邏輯閘
重命名 重新命名
重裝 重灌
重載 過載
金屬氧化物半導體 金氧半導體
錄像 錄影
鏈接 連結
鏈表 連結串列
鏡像 映象
門戶網站 入口網站
門電路 閘電路
閃存 快閃記憶體
關係數據庫 關聯式資料庫
隊列 佇列
集成 整合
集成電路 積體電路
集羣 叢集
雲存儲 雲端儲存
雲計算 雲端計算
面向對象 物件導向
面向過程 程序導向
音頻 音訊
頁眉 頁首
頁腳 頁尾
項目 專案
預處理器 前處理器
頭文件 標頭檔案
頻分多址 分頻多重進接
頻分複用 分頻多工
類型 型別
類模板 類别範本
顯像管 映象管
顯卡 顯示卡
顯存 視訊記憶體
飛行模式 飛航模式
首席信息官 資訊長
首席執行官 執行長
首席技術官 技術長
首席運營官 營運長
高性能計算 高效能運算
高清 高畫質
高端 高階 進階
高級 高階 進階 高級
高速緩存 快取記憶體
黑客 駭客
默認 預設
默認值 預設值
點擊 點選
鼠標 滑鼠

View File

@@ -0,0 +1,84 @@
乍得 查德
也門 葉門
仙童半導體 快捷半導體
伯利茲 貝里斯
佛得角 維德角
傅里葉 傅立葉
克羅地亞 克羅埃西亞
列支敦士登 列支敦斯登
利比里亞 賴比瑞亞
加納 迦納
加蓬 加彭
博茨瓦納 波札那
卡塔爾 卡達
危地馬拉 瓜地馬拉
厄瓜多爾 厄瓜多
厄立特里亞 厄利垂亞
吉布堤 吉布地
哈薩克斯坦 哈薩克
哥斯達黎加 哥斯大黎加
喫茶小舖 喫茶小舖
圖瓦盧 吐瓦魯
土庫曼斯坦 土庫曼
圭亞那 蓋亞那
坦桑尼亞 坦尚尼亞
埃塞俄比亞 衣索比亞
基里巴斯 吉里巴斯
塔吉克斯坦 塔吉克
塞拉利昂 獅子山
塞浦路斯 塞普勒斯
塞舌爾 塞席爾
多米尼加 多明尼加
安提瓜和巴布達 安地卡及巴布達
尼日利亞 奈及利亞
尼日爾 尼日
岡比亞 甘比亞
巴巴多斯 巴貝多
巴布亞新幾內亞 巴布亞紐幾內亞
布基納法索 布吉納法索
布隆迪 蒲隆地
帕勞 帛琉
幾內亞比紹 幾內亞比索
意大利 義大利
所羅門羣島 索羅門羣島
文萊 汶萊
斯威士蘭 史瓦濟蘭
斯洛文尼亞 斯洛維尼亞
新西蘭 紐西蘭
格林納達 格瑞那達
格魯吉亞 喬治亞
歐拉 尤拉
毛里塔尼亞 茅利塔尼亞
毛里求斯 模里西斯
沙特阿拉伯 沙烏地阿拉伯
波斯尼亞黑塞哥維那 波士尼亞赫塞哥維納
津巴布韋 辛巴威
洪都拉斯 宏都拉斯
溫納圖萬 那杜
烏茲別克斯坦 烏茲別克
特立尼達和多巴哥 千里達及托巴哥
瑙魯 諾魯
瓦努阿圖 萬那杜
盧旺達 盧安達
科摩羅 葛摩
科特迪瓦 象牙海岸
突尼斯 突尼西亞
純喫茶 純喫茶
索馬里 索馬利亞
老撾 寮國
聖基茨和尼維斯 聖克里斯多福及尼維斯
聖文森特和格林納丁斯 聖文森及格瑞那丁
聖盧西亞 聖露西亞
聖馬力諾 聖馬利諾
肯尼亞 肯亞
莫桑比克 莫三比克
萊索托 賴索托
萬象 永珍
蘇里南 蘇利南
貝寧 貝南
贊比亞 尚比亞
阿塞拜疆 亞塞拜然
阿拉伯聯合酋長國 阿拉伯聯合大公國
香農 夏農
馬爾代夫 馬爾地夫
馬里共和國 馬利共和國

View File

@@ -0,0 +1,37 @@
元音 母音
冰棍 冰棒
出租車 計程車
咖喱 咖哩
塑料 塑膠
奔馳 賓士
奶酪 乳酪
幾率 機率
方便麪 泡麵 速食麵
李彥宏 李彥宏
概率 機率
海內存知己 海內存知己
涼菜 冷盤
的士 計程車
砹 砈
硅 矽
程序不正義 程序不正義
程序正義 程序正義
空氣淨化器 空氣清淨機
納米 奈米
自行車 腳踏車
詞組 片語
蹦極 高空彈跳
輔音 子音
通過 透過 通過
酰 醯
鈁 鍅
鈈 鈽
錇 鉳
鍀 鎝
鎄 鑀
鎇 鋂
鎿 錼
鐦 鉲
鑥 鎦
黃宏 黃宏
借記卡 簽帳金融卡

View File

@@ -0,0 +1,39 @@
僞 偽
啓 啟
喫 吃
嫺 嫻
嬀 媯
峯 峰
幺 么
擡 抬
棱 稜
檐 簷
污 汙
泄 洩
潙 溈
潨 潀
爲 為
牀 床
痹 痺
癡 痴
皁 皂
着 著
睾 睪
祕 秘
竈 灶
糉 粽
繮 韁
纔 才
羣 群
脣 唇
蔘 參
蔿 蒍
衆 眾
裏 裡
覈 核
踊 踴
鉢 缽
鍼 針
鮎 鯰
麪 麵
齶 顎

View File

@@ -0,0 +1,68 @@
一口吃個 一口喫個
一口吃成 一口喫成
一家三口 一家三口
一家五口 一家五口
一家六口 一家六口
一家四口 一家四口
凶事 凶事
凶信 凶信
凶兆 凶兆
凶吉 凶吉
凶地 凶地
凶多吉少 凶多吉少
凶宅 凶宅
凶年 凶年
凶德 凶德
凶怪 凶怪
凶日 凶日
凶服 凶服
凶歲 凶歲
凶死 凶死
凶氣 凶氣
凶煞 凶煞
凶燄 凶燄
凶神 凶神
凶禮 凶禮
凶耗 凶耗
凶肆 凶肆
凶荒 凶荒
凶訊 凶訊
凶豎 凶豎
凶身 凶身
凶逆 凶逆
凶門 凶門
口吃 口吃
吃口 喫口 吃口
吃口令 吃口令
吃口飯 喫口飯
吃吃 喫喫 吃吃
吃子 喫子 吃子
合著 合著
吉凶 吉凶
名著 名著
四凶 四凶
大凶 大凶
巨著 巨著
張口 張口
昭著 昭著
歲凶 歲凶
胃口 胃口
著作 著作
著名 著名
著式 著式
著志 著志
著於 著於
著書 著書
著白 著白
著稱 著稱
著者 著者
著述 著述
著錄 著錄
蹇吃 蹇吃
逢凶 逢凶
避凶 避凶
鄧艾吃 鄧艾吃
鉅著 鉅著
開口 開口
閔凶 閔凶
顯著 顯著

View File

@@ -0,0 +1,65 @@
<?php return array (
'僞' => '偽',
'兌' => '兑',
'叄' => '叁',
'只' => '只',
'啓' => '啓',
'喫' => '吃',
'囪' => '囱',
'妝' => '妝',
'媼' => '媪',
'嬀' => '媯',
'悅' => '悦',
'慍' => '愠',
'戶' => '户',
'挩' => '捝',
'搵' => '揾',
'擡' => '抬',
'敓' => '敚',
'敘' => '敍',
'柺' => '枴',
'梲' => '棁',
'棱' => '稜',
'榲' => '榅',
'檯' => '枱',
'氳' => '氲',
'涗' => '涚',
'溫' => '温',
'溼' => '濕',
'潙' => '溈',
'潨' => '潀',
'熅' => '煴',
'爲' => '為',
'癡' => '痴',
'皁' => '皂',
'祕' => '秘',
'稅' => '税',
'竈' => '灶',
'糉' => '粽',
'縕' => '緼',
'纔' => '才',
'脣' => '唇',
'脫' => '脱',
'膃' => '腽',
'臥' => '卧',
'臺' => '台',
'菸' => '煙',
'蒕' => '蒀',
'蔥' => '葱',
'蔿' => '蒍',
'蘊' => '藴',
'蛻' => '蜕',
'衆' => '眾',
'衛' => '衞',
'覈' => '核',
'說' => '説',
'踊' => '踴',
'轀' => '輼',
'醞' => '醖',
'鉢' => '缽',
'鉤' => '鈎',
'銳' => '鋭',
'鍼' => '針',
'閱' => '閲',
'鰮' => '鰛',
);

View File

@@ -0,0 +1,65 @@
<?php return array (
'偽' => '僞',
'兑' => '兌',
'叁' => '叄',
'只' => '只',
'啓' => '啓',
'吃' => '喫',
'囱' => '囪',
'妝' => '妝',
'媪' => '媼',
'媯' => '嬀',
'悦' => '悅',
'愠' => '慍',
'户' => '戶',
'捝' => '挩',
'揾' => '搵',
'抬' => '擡',
'敚' => '敓',
'敍' => '敘',
'枴' => '柺',
'棁' => '梲',
'稜' => '棱',
'榅' => '榲',
'枱' => '檯',
'氲' => '氳',
'涚' => '涗',
'温' => '溫',
'濕' => '溼',
'溈' => '潙',
'潀' => '潨',
'煴' => '熅',
'為' => '爲',
'痴' => '癡',
'皂' => '皁',
'秘' => '祕',
'税' => '稅',
'灶' => '竈',
'粽' => '糉',
'緼' => '縕',
'才' => '纔',
'唇' => '脣',
'脱' => '脫',
'腽' => '膃',
'卧' => '臥',
'台' => '臺',
'煙' => '菸',
'蒀' => '蒕',
'葱' => '蔥',
'蒍' => '蔿',
'藴' => '蘊',
'蜕' => '蛻',
'眾' => '衆',
'衞' => '衛',
'核' => '覈',
'説' => '說',
'踴' => '踊',
'輼' => '轀',
'醖' => '醞',
'缽' => '鉢',
'鈎' => '鉤',
'鋭' => '銳',
'針' => '鍼',
'閲' => '閱',
'鰛' => '鰮',
);

View File

@@ -0,0 +1,158 @@
<?php return array (
'一口吃個' => '一口喫個',
'一口吃成' => '一口喫成',
'一家三口' => '一家三口',
'一家五口' => '一家五口',
'一家六口' => '一家六口',
'一家四口' => '一家四口',
'七星巖' => '七星巖',
'世胄' => '世胄',
'介胄' => '介冑',
'傅巖' => '傅巖',
'免胄' => '免冑',
'冠胄' => '冠冑',
'千巖競秀' => '千巖競秀',
'千巖萬壑' => '千巖萬壑',
'千巖萬谷' => '千巖萬谷',
'口吃' => '口吃',
'台山' => '台山',
'台州' => '台州',
'台州地區' => '台州地區',
'台州市' => '台州市',
'吃口' => '喫口',
'吃口令' => '吃口令',
'吃口飯' => '喫口飯',
'吃吃' => '喫喫',
'吃子' => '喫子',
'名胄' => '名胄',
'國胄' => '國胄',
'圍巖' => '圍巖',
'地胄' => '地胄',
'壓胄子' => '壓冑子',
'士胄' => '士胄',
'大巖桐' => '大巖桐',
'天台女' => '天台女',
'天台宗' => '天台宗',
'天台山' => '天台山',
'天台縣' => '天台縣',
'天潢貴胄' => '天潢貴胄',
'奇巖' => '奇巖',
'寶胄' => '寶胄',
'小巖洞' => '小巖洞',
'岫巖縣' => '岫巖縣',
'峯巖' => '峯巖',
'嵌巖' => '嵌巖',
'巉巖' => '巉巖',
'巖壁' => '巖壁',
'巖居' => '巖居',
'巖居穴處' => '巖居穴處',
'巖居谷飲' => '巖居谷飲',
'巖岸' => '巖岸',
'巖巉' => '巖巉',
'巖巖' => '巖巖',
'巖徼' => '巖徼',
'巖手縣' => '巖手縣',
'巖村' => '巖村',
'巖洞' => '巖洞',
'巖流圈' => '巖流圈',
'巖牆' => '巖牆',
'巖牆之下' => '巖牆之下',
'巖畫' => '巖畫',
'巖穴' => '巖穴',
'巖穴之士' => '巖穴之士',
'巖薔薇' => '巖薔薇',
'巖邑' => '巖邑',
'巖郎' => '巖郎',
'巖阻' => '巖阻',
'巖陛' => '巖陛',
'帝胄' => '帝胄',
'幽巖' => '幽巖',
'幽棲巖谷' => '幽棲巖谷',
'張口' => '張口',
'懸巖' => '懸巖',
'懸巖峭壁' => '懸巖峭壁',
'懸胄' => '懸冑',
'攀巖' => '攀巖',
'支胄' => '支胄',
'教胄' => '教胄',
'景胄' => '景胄',
'望胄' => '望胄',
'末胄' => '末胄',
'村胄' => '村胄',
'枕巖漱流' => '枕巖漱流',
'枝胄' => '枝胄',
'氏胄' => '氏胄',
'洪胄' => '洪胄',
'浙江天台縣' => '浙江天台縣',
'清胄' => '清胄',
'灰巖殘丘' => '灰巖殘丘',
'玄胄' => '玄胄',
'甲胄' => '甲冑',
'甲胄魚類' => '甲冑魚類',
'皇胄' => '皇胄',
'石灰巖洞' => '石灰巖洞',
'神胄' => '神胄',
'簪纓世胄' => '簪纓世胄',
'系胄' => '系胄',
'紅巖' => '紅巖',
'絕巖' => '絕巖',
'緒胄' => '緒胄',
'纂胄' => '纂胄',
'胃口' => '胃口',
'胄嗣' => '胄嗣',
'胄子' => '胄子',
'胄序' => '胄序',
'胄族' => '胄族',
'胄甲' => '冑甲',
'胄監' => '胄監',
'胄科' => '冑科',
'胄緒' => '胄緒',
'胄胤' => '胄胤',
'胄裔' => '胄裔',
'胄裔繁衍' => '胄裔繁衍',
'胄閥' => '胄閥',
'胡雪巖' => '胡雪巖',
'胤胄' => '胤胄',
'苗胄' => '苗胄',
'英胄' => '英胄',
'華胄' => '華胄',
'血胄' => '血胄',
'裔胄' => '裔胄',
'訓胄' => '訓胄',
'試胄' => '試胄',
'豪門貴胄' => '豪門貴胄',
'貝胄' => '貝冑',
'貴胄' => '貴胄',
'賢胄' => '賢胄',
'蹇吃' => '蹇吃',
'躬擐甲胄' => '躬擐甲冑',
'遐胄' => '遐胄',
'遙胄' => '遙胄',
'遙遙華胄' => '遙遙華胄',
'遠胄' => '遠胄',
'遺胄' => '遺胄',
'鄧艾吃' => '鄧艾吃',
'重巖疊嶂' => '重巖疊嶂',
'金胄' => '金胄',
'鎧胄' => '鎧冑',
'鑿巖' => '鑿巖',
'門胄' => '門胄',
'開口' => '開口',
'雲巖區' => '雲巖區',
'非層巖' => '非層巖',
'韓侂胄' => '韓侂冑',
'飮胄' => '飮冑',
'骨巖巖' => '骨巖巖',
'高胄' => '高胄',
'魚胄' => '魚冑',
'鮮胄' => '鮮胄',
'鴻胄' => '鴻胄',
'黃巖區' => '黃巖區',
'黃巖島' => '黃巖島',
'黃炎貴胄' => '黃炎貴胄',
'齒胄' => '齒胄',
'龍巖' => '龍巖',
'龍巖市' => '龍巖市',
'龍巖村' => '龍巖村',
'龍胄' => '龍胄',
);

View File

@@ -0,0 +1,9 @@
<?php return array (
'両' => '兩',
'弁' => '辨',
'御' => '御',
'欠' => '缺',
'糸' => '絲',
'芸' => '藝',
'浜' => '濱',
);

View File

@@ -0,0 +1,178 @@
<?php return array (
'一獲千金' => '一攫千金',
'丁寧' => '叮嚀',
'丁重' => '鄭重',
'三差路' => '三叉路',
'世論' => '輿論',
'亜鈴' => '啞鈴',
'交差' => '交叉',
'供宴' => '饗宴',
'俊馬' => '駿馬',
'保塁' => '堡壘',
'個条書' => '箇条書',
'偏平' => '扁平',
'停泊' => '碇泊',
'優俊' => '優駿',
'先兵' => '尖兵',
'先鋭' => '尖鋭',
'共役' => '共軛',
'冗舌' => '饒舌',
'凶器' => '兇器',
'削岩' => '鑿岩',
'包丁' => '庖丁',
'包帯' => '繃帯',
'区画' => '區劃',
'厳然' => '儼然',
'友宜' => '友誼',
'反乱' => '叛乱',
'収集' => '蒐集',
'叙情' => '抒情',
'台頭' => '擡頭',
'合弁' => '合辦',
'喜遊曲' => '嬉遊曲',
'嘆願' => '歎願',
'回転' => '廻転',
'回遊' => '回游',
'奉持' => '捧持',
'委縮' => '萎縮',
'展転' => '輾轉',
'希少' => '稀少',
'幻惑' => '眩惑',
'広範' => '廣汎',
'広野' => '曠野',
'廃虚' => '廢墟',
'建坪率' => '建蔽率',
'弁当' => '辨當',
'弁膜' => '瓣膜',
'弁護' => '辯護',
'弁髪' => '辮髮',
'弦歌' => '絃歌',
'恩義' => '恩誼',
'意向' => '意嚮',
'慰謝料' => '慰藉料',
'憶断' => '臆断',
'憶病' => '臆病',
'戦没' => '戰歿',
'扇情' => '煽情',
'手帳' => '手帖',
'技量' => '伎倆',
'抜粋' => '抜萃',
'披歴' => '披瀝',
'抵触' => '牴触',
'抽選' => '抽籤',
'拘引' => '勾引',
'拠出' => '醵出',
'拠金' => '醵金',
'掘削' => '掘鑿',
'控除' => '扣除',
'援護' => '掩護',
'放棄' => '抛棄',
'散水' => '撒水',
'敬謙' => '敬虔',
'敷延' => '敷衍',
'断固' => '断乎',
'族生' => '簇生',
'昇叙' => '陞敘',
'暖房' => '煖房',
'暗唱' => '暗誦',
'暗夜' => '闇夜',
'暴露' => '曝露',
'枯渇' => '涸渇',
'格好' => '恰好',
'格幅' => '恰幅',
'棄損' => '毀損',
'模索' => '摸索',
'橋頭保' => '橋頭堡',
'欠缺' => '欠缺',
'死体' => '屍體',
'殿部' => '臀部',
'母指' => '拇指',
'気迫' => '気魄',
'決別' => '訣別',
'決壊' => '決潰',
'沈殿' => '沈澱',
'油送船' => '油槽船',
'波乱' => '波瀾',
'注釈' => '註釋',
'洗浄' => '洗滌',
'活発' => '活潑',
'浸透' => '滲透',
'浸食' => '浸蝕',
'消却' => '銷卻',
'混然' => '渾然',
'湾曲' => '彎曲',
'溶接' => '熔接',
'漁労' => '漁撈',
'漂然' => '飄然',
'激高' => '激昂',
'火炎' => '火焰',
'焦燥' => '焦躁',
'班点' => '斑点',
'留飲' => '溜飲',
'略奪' => '掠奪',
'疎通' => '疏通',
'発酵' => '醱酵',
'白亜' => '白堊',
'相克' => '相剋',
'知恵' => '智慧',
'破棄' => '破毀',
'確固' => '確乎',
'禁固' => '禁錮',
'符丁' => '符牒',
'粉装' => '扮装',
'紫班' => '紫斑',
'終息' => '終熄',
'総合' => '綜合',
'編集' => '編輯',
'義援' => '義捐',
'耕運機' => '耕耘機',
'肝心' => '肝腎',
'肩甲骨' => '肩胛骨',
'背徳' => '悖德',
'脈拍' => '脈搏',
'膨張' => '膨脹',
'芳純' => '芳醇',
'英知' => '叡智',
'蒸留' => '蒸溜',
'薫蒸' => '燻蒸',
'薫製' => '燻製',
'衣装' => '衣裳',
'衰退' => '衰退',
'裕然' => '悠然',
'補佐' => '輔佐',
'訓戒' => '訓誡',
'試練' => '試煉',
'詭弁' => '詭辯',
'講和' => '媾和',
'象眼' => '象嵌',
'貫録' => '貫禄',
'買弁' => '買辦',
'賛辞' => '讚辭',
'踏襲' => '蹈襲',
'車両' => '車輛',
'転倒' => '顛倒',
'輪郭' => '輪廓',
'退色' => '褪色',
'途絶' => '杜絶',
'連係' => '連繫',
'連合' => '聯合',
'選考' => '銓衡',
'酢酸' => '醋酸',
'野卑' => '野鄙',
'鉱石' => '礦石',
'間欠' => '間歇',
'関数' => '函數',
'防御' => '防禦',
'険阻' => '嶮岨',
'障壁' => '牆壁',
'障害' => '障礙',
'隠滅' => '湮滅',
'集落' => '聚落',
'雇用' => '雇傭',
'風諭' => '諷喩',
'飛語' => '蜚語',
'香典' => '香奠',
'骨格' => '骨骼',
'高進' => '亢進',
'鳥観' => '鳥瞰',
);

View File

@@ -0,0 +1,369 @@
<?php return array (
'乘' => '乗',
'亂' => '乱',
'亙' => '亘',
'亞' => '亜',
'佛' => '仏',
'來' => '来',
'假' => '仮',
'傳' => '伝',
'僞' => '偽',
'價' => '価',
'儉' => '倹',
'兒' => '児',
'內' => '内',
'兩' => '両',
'剎' => '刹',
'剩' => '剰',
'劍' => '剣',
'劑' => '剤',
'勞' => '労',
'勳' => '勲',
'勵' => '励',
'勸' => '勧',
'勻' => '匀',
'區' => '区',
'卷' => '巻',
'卻' => '却',
'參' => '参',
'吳' => '呉',
'咒' => '呪',
'啞' => '唖',
'單' => '単',
'噓' => '嘘',
'嚙' => '噛',
'嚴' => '厳',
'囑' => '嘱',
'圈' => '圏',
'國' => '国',
'圍' => '囲',
'圓' => '円',
'圖' => '図',
'團' => '団',
'增' => '増',
'墮' => '堕',
'壓' => '圧',
'壘' => '塁',
'壞' => '壊',
'壤' => '壌',
'壯' => '壮',
'壹' => '壱',
'壽' => '寿',
'奧' => '奥',
'奬' => '奨',
'妝' => '粧',
'孃' => '嬢',
'學' => '学',
'寢' => '寝',
'實' => '実',
'寫' => '写',
'寬' => '寛',
'寶' => '宝',
'將' => '将',
'專' => '専',
'對' => '対',
'屆' => '届',
'屬' => '属',
'峯' => '峰',
'峽' => '峡',
'嶽' => '岳',
'巖' => '巌',
'巢' => '巣',
'帶' => '帯',
'廁' => '厠',
'廢' => '廃',
'廣' => '広',
'廳' => '庁',
'彈' => '弾',
'彌' => '弥',
'彎' => '弯',
'彥' => '彦',
'徑' => '径',
'從' => '従',
'徵' => '徴',
'德' => '徳',
'恆' => '恒',
'悅' => '悦',
'惠' => '恵',
'惡' => '悪',
'惱' => '悩',
'慘' => '惨',
'應' => '応',
'懷' => '懐',
'戀' => '恋',
'戰' => '戦',
'戲' => '戯',
'戶' => '戸',
'戾' => '戻',
'拂' => '払',
'拔' => '抜',
'拜' => '拝',
'挾' => '挟',
'插' => '挿',
'揭' => '掲',
'搔' => '掻',
'搖' => '揺',
'搜' => '捜',
'摑' => '掴',
'擇' => '択',
'擊' => '撃',
'擔' => '担',
'據' => '拠',
'擴' => '拡',
'攝' => '摂',
'攪' => '撹',
'收' => '収',
'效' => '効',
'敕' => '勅',
'敘' => '叙',
'數' => '数',
'斷' => '断',
'晉' => '晋',
'晚' => '晩',
'晝' => '昼',
'暨' => '曁',
'曆' => '暦',
'曉' => '暁',
'曾' => '曽',
'會' => '会',
'枡' => '桝',
'查' => '査',
'條' => '条',
'棧' => '桟',
'棱' => '稜',
'榆' => '楡',
'榮' => '栄',
'樂' => '楽',
'樓' => '楼',
'樞' => '枢',
'樣' => '様',
'橫' => '横',
'檢' => '検',
'櫻' => '桜',
'權' => '権',
'歐' => '欧',
'歡' => '歓',
'步' => '歩',
'歲' => '歳',
'歷' => '歴',
'歸' => '帰',
'殘' => '残',
'殼' => '殻',
'毆' => '殴',
'每' => '毎',
'氣' => '気',
'污' => '汚',
'沒' => '没',
'涉' => '渉',
'淚' => '涙',
'淨' => '浄',
'淺' => '浅',
'渴' => '渇',
'潑' => '溌',
'溪' => '渓',
'溫' => '温',
'溼' => '湿',
'滯' => '滞',
'滿' => '満',
'潛' => '潜',
'澀' => '渋',
'澤' => '沢',
'濟' => '済',
'濤' => '涛',
'濱' => '浜',
'濾' => '沪',
'瀧' => '滝',
'瀨' => '瀬',
'灣' => '湾',
'焰' => '焔',
'燈' => '灯',
'燒' => '焼',
'營' => '営',
'爐' => '炉',
'爭' => '争',
'爲' => '為',
'牀' => '床',
'犧' => '犠',
'狀' => '状',
'狹' => '狭',
'獨' => '独',
'獵' => '猟',
'獸' => '獣',
'獻' => '献',
'瓣' => '弁',
'產' => '産',
'畫' => '画',
'當' => '当',
'疊' => '畳',
'疎' => '疏',
'痹' => '痺',
'瘦' => '痩',
'癡' => '痴',
'發' => '発',
'皋' => '皐',
'盜' => '盗',
'盡' => '尽',
'碎' => '砕',
'祕' => '秘',
'祿' => '禄',
'禦' => '御',
'禪' => '禅',
'禮' => '礼',
'禱' => '祷',
'稅' => '税',
'稱' => '称',
'稻' => '稲',
'穎' => '頴',
'穗' => '穂',
'穩' => '穏',
'穰' => '穣',
'竈' => '竃',
'竊' => '窃',
'粹' => '粋',
'糉' => '粽',
'絕' => '絶',
'絲' => '糸',
'經' => '経',
'綠' => '緑',
'緖' => '緒',
'緣' => '縁',
'縣' => '県',
'縱' => '縦',
'總' => '総',
'繫' => '繋',
'繡' => '繍',
'繩' => '縄',
'繪' => '絵',
'繼' => '継',
'續' => '続',
'纔' => '才',
'纖' => '繊',
'缺' => '欠',
'罐' => '缶',
'羣' => '群',
'聯' => '連',
'聰' => '聡',
'聲' => '声',
'聽' => '聴',
'肅' => '粛',
'脣' => '唇',
'脫' => '脱',
'腦' => '脳',
'腳' => '脚',
'膽' => '胆',
'臟' => '臓',
'臺' => '台',
'與' => '与',
'舉' => '挙',
'舊' => '旧',
'舍' => '舎',
'荔' => '茘',
'莊' => '荘',
'莖' => '茎',
'菸' => '煙',
'萊' => '莱',
'萬' => '万',
'蔣' => '蒋',
'蔥' => '葱',
'薰' => '薫',
'藏' => '蔵',
'藝' => '芸',
'藥' => '薬',
'蘆' => '芦',
'處' => '処',
'虛' => '虚',
'號' => '号',
'螢' => '蛍',
'蟲' => '虫',
'蠟' => '蝋',
'蠶' => '蚕',
'蠻' => '蛮',
'裝' => '装',
'覺' => '覚',
'覽' => '覧',
'觀' => '観',
'觸' => '触',
'說' => '説',
'謠' => '謡',
'證' => '証',
'譯' => '訳',
'譽' => '誉',
'讀' => '読',
'變' => '変',
'讓' => '譲',
'豐' => '豊',
'豫' => '予',
'貓' => '猫',
'貳' => '弐',
'賣' => '売',
'賴' => '頼',
'贊' => '賛',
'贗' => '贋',
'踐' => '践',
'輕' => '軽',
'輛' => '輌',
'轉' => '転',
'辨' => '弁',
'辭' => '辞',
'辯' => '弁',
'遞' => '逓',
'遥' => '遙',
'遲' => '遅',
'邊' => '辺',
'鄉' => '郷',
'酢' => '醋',
'醉' => '酔',
'醱' => '醗',
'醫' => '医',
'醬' => '醤',
'釀' => '醸',
'釋' => '釈',
'鋪' => '舗',
'錄' => '録',
'錢' => '銭',
'鍊' => '錬',
'鐵' => '鉄',
'鑄' => '鋳',
'鑛' => '鉱',
'閱' => '閲',
'關' => '関',
'陷' => '陥',
'隨' => '随',
'險' => '険',
'隱' => '隠',
'雙' => '双',
'雜' => '雑',
'雞' => '鶏',
'霸' => '覇',
'靈' => '霊',
'靜' => '静',
'顏' => '顔',
'顯' => '顕',
'餘' => '余',
'騷' => '騒',
'驅' => '駆',
'驗' => '験',
'驛' => '駅',
'髓' => '髄',
'體' => '体',
'髮' => '髪',
'鬥' => '闘',
'鱉' => '鼈',
'鷗' => '鴎',
'鹼' => '鹸',
'鹽' => '塩',
'麥' => '麦',
'麪' => '麺',
'麴' => '麹',
'黃' => '黄',
'黑' => '黒',
'默' => '黙',
'點' => '点',
'黨' => '党',
'齊' => '斉',
'齋' => '斎',
'齒' => '歯',
'齡' => '齢',
'龍' => '竜',
'龜' => '亀',
);

View File

@@ -0,0 +1,367 @@
<?php return array (
'乗' => '乘',
'乱' => '亂',
'亘' => '亙',
'亜' => '亞',
'仏' => '佛',
'来' => '來',
'仮' => '假',
'伝' => '傳',
'偽' => '僞',
'価' => '價',
'倹' => '儉',
'児' => '兒',
'内' => '內',
'両' => '兩',
'刹' => '剎',
'剰' => '剩',
'剣' => '劍',
'剤' => '劑',
'労' => '勞',
'勲' => '勳',
'励' => '勵',
'勧' => '勸',
'匀' => '勻',
'区' => '區',
'巻' => '卷',
'却' => '卻',
'参' => '參',
'呉' => '吳',
'呪' => '咒',
'唖' => '啞',
'単' => '單',
'嘘' => '噓',
'噛' => '嚙',
'厳' => '嚴',
'嘱' => '囑',
'圏' => '圈',
'国' => '國',
'囲' => '圍',
'円' => '圓',
'図' => '圖',
'団' => '團',
'増' => '增',
'堕' => '墮',
'圧' => '壓',
'塁' => '壘',
'壊' => '壞',
'壌' => '壤',
'壮' => '壯',
'壱' => '壹',
'寿' => '壽',
'奥' => '奧',
'奨' => '奬',
'粧' => '妝',
'嬢' => '孃',
'学' => '學',
'寝' => '寢',
'実' => '實',
'写' => '寫',
'寛' => '寬',
'宝' => '寶',
'将' => '將',
'専' => '專',
'対' => '對',
'届' => '屆',
'属' => '屬',
'峰' => '峯',
'峡' => '峽',
'岳' => '嶽',
'巌' => '巖',
'巣' => '巢',
'帯' => '帶',
'厠' => '廁',
'廃' => '廢',
'広' => '廣',
'庁' => '廳',
'弾' => '彈',
'弥' => '彌',
'弯' => '彎',
'彦' => '彥',
'径' => '徑',
'従' => '從',
'徴' => '徵',
'徳' => '德',
'恒' => '恆',
'悦' => '悅',
'恵' => '惠',
'悪' => '惡',
'悩' => '惱',
'惨' => '慘',
'応' => '應',
'懐' => '懷',
'恋' => '戀',
'戦' => '戰',
'戯' => '戲',
'戸' => '戶',
'戻' => '戾',
'払' => '拂',
'抜' => '拔',
'拝' => '拜',
'挟' => '挾',
'挿' => '插',
'掲' => '揭',
'掻' => '搔',
'揺' => '搖',
'捜' => '搜',
'掴' => '摑',
'択' => '擇',
'撃' => '擊',
'担' => '擔',
'拠' => '據',
'拡' => '擴',
'摂' => '攝',
'撹' => '攪',
'収' => '收',
'効' => '效',
'勅' => '敕',
'叙' => '敘',
'数' => '數',
'断' => '斷',
'晋' => '晉',
'晩' => '晚',
'昼' => '晝',
'曁' => '暨',
'暦' => '曆',
'暁' => '曉',
'曽' => '曾',
'会' => '會',
'桝' => '枡',
'査' => '查',
'条' => '條',
'桟' => '棧',
'稜' => '棱',
'楡' => '榆',
'栄' => '榮',
'楽' => '樂',
'楼' => '樓',
'枢' => '樞',
'様' => '樣',
'横' => '橫',
'検' => '檢',
'桜' => '櫻',
'権' => '權',
'欧' => '歐',
'歓' => '歡',
'歩' => '步',
'歳' => '歲',
'歴' => '歷',
'帰' => '歸',
'残' => '殘',
'殻' => '殼',
'殴' => '毆',
'毎' => '每',
'気' => '氣',
'汚' => '污',
'没' => '沒',
'渉' => '涉',
'涙' => '淚',
'浄' => '淨',
'浅' => '淺',
'渇' => '渴',
'溌' => '潑',
'渓' => '溪',
'温' => '溫',
'湿' => '溼',
'滞' => '滯',
'満' => '滿',
'潜' => '潛',
'渋' => '澀',
'沢' => '澤',
'済' => '濟',
'涛' => '濤',
'浜' => '濱',
'沪' => '濾',
'滝' => '瀧',
'瀬' => '瀨',
'湾' => '灣',
'焔' => '焰',
'灯' => '燈',
'焼' => '燒',
'営' => '營',
'炉' => '爐',
'争' => '爭',
'為' => '爲',
'床' => '牀',
'犠' => '犧',
'状' => '狀',
'狭' => '狹',
'独' => '獨',
'猟' => '獵',
'獣' => '獸',
'献' => '獻',
'弁' => '辯',
'産' => '產',
'画' => '畫',
'当' => '當',
'畳' => '疊',
'疏' => '疎',
'痺' => '痹',
'痩' => '瘦',
'痴' => '癡',
'発' => '發',
'皐' => '皋',
'盗' => '盜',
'尽' => '盡',
'砕' => '碎',
'秘' => '祕',
'禄' => '祿',
'御' => '禦',
'禅' => '禪',
'礼' => '禮',
'祷' => '禱',
'税' => '稅',
'称' => '稱',
'稲' => '稻',
'頴' => '穎',
'穂' => '穗',
'穏' => '穩',
'穣' => '穰',
'竃' => '竈',
'窃' => '竊',
'粋' => '粹',
'粽' => '糉',
'絶' => '絕',
'糸' => '絲',
'経' => '經',
'緑' => '綠',
'緒' => '緖',
'縁' => '緣',
'県' => '縣',
'縦' => '縱',
'総' => '總',
'繋' => '繫',
'繍' => '繡',
'縄' => '繩',
'絵' => '繪',
'継' => '繼',
'続' => '續',
'才' => '纔',
'繊' => '纖',
'欠' => '缺',
'缶' => '罐',
'群' => '羣',
'連' => '聯',
'聡' => '聰',
'声' => '聲',
'聴' => '聽',
'粛' => '肅',
'唇' => '脣',
'脱' => '脫',
'脳' => '腦',
'脚' => '腳',
'胆' => '膽',
'臓' => '臟',
'台' => '臺',
'与' => '與',
'挙' => '舉',
'旧' => '舊',
'舎' => '舍',
'茘' => '荔',
'荘' => '莊',
'茎' => '莖',
'煙' => '菸',
'莱' => '萊',
'万' => '萬',
'蒋' => '蔣',
'葱' => '蔥',
'薫' => '薰',
'蔵' => '藏',
'芸' => '藝',
'薬' => '藥',
'芦' => '蘆',
'処' => '處',
'虚' => '虛',
'号' => '號',
'蛍' => '螢',
'虫' => '蟲',
'蝋' => '蠟',
'蚕' => '蠶',
'蛮' => '蠻',
'装' => '裝',
'覚' => '覺',
'覧' => '覽',
'観' => '觀',
'触' => '觸',
'説' => '說',
'謡' => '謠',
'証' => '證',
'訳' => '譯',
'誉' => '譽',
'読' => '讀',
'変' => '變',
'譲' => '讓',
'豊' => '豐',
'予' => '豫',
'猫' => '貓',
'弐' => '貳',
'売' => '賣',
'頼' => '賴',
'賛' => '贊',
'贋' => '贗',
'践' => '踐',
'軽' => '輕',
'輌' => '輛',
'転' => '轉',
'辞' => '辭',
'逓' => '遞',
'遙' => '遥',
'遅' => '遲',
'辺' => '邊',
'郷' => '鄉',
'醋' => '酢',
'酔' => '醉',
'醗' => '醱',
'医' => '醫',
'醤' => '醬',
'醸' => '釀',
'釈' => '釋',
'舗' => '鋪',
'録' => '錄',
'銭' => '錢',
'錬' => '鍊',
'鉄' => '鐵',
'鋳' => '鑄',
'鉱' => '鑛',
'閲' => '閱',
'関' => '關',
'陥' => '陷',
'随' => '隨',
'険' => '險',
'隠' => '隱',
'双' => '雙',
'雑' => '雜',
'鶏' => '雞',
'覇' => '霸',
'霊' => '靈',
'静' => '靜',
'顔' => '顏',
'顕' => '顯',
'余' => '餘',
'騒' => '騷',
'駆' => '驅',
'験' => '驗',
'駅' => '驛',
'髄' => '髓',
'体' => '體',
'髪' => '髮',
'闘' => '鬥',
'鼈' => '鱉',
'鴎' => '鷗',
'鹸' => '鹼',
'塩' => '鹽',
'麦' => '麥',
'麺' => '麪',
'麹' => '麴',
'黄' => '黃',
'黒' => '黑',
'黙' => '默',
'点' => '點',
'党' => '黨',
'斉' => '齊',
'斎' => '齋',
'歯' => '齒',
'齢' => '齡',
'竜' => '龍',
'亀' => '龜',
);

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,279 @@
<?php return array (
'一目瞭然' => '一目了然',
'上鍊' => '上链',
'不瞭解' => '不了解',
'么麼' => '幺麽',
'么麽' => '幺麽',
'乾乾淨淨' => '干干净净',
'乾乾脆脆' => '干干脆脆',
'乾元' => '乾元',
'乾卦' => '乾卦',
'乾嘉' => '乾嘉',
'乾圖' => '乾图',
'乾坤' => '乾坤',
'乾坤一擲' => '乾坤一掷',
'乾坤再造' => '乾坤再造',
'乾坤大挪移' => '乾坤大挪移',
'乾宅' => '乾宅',
'乾斷' => '乾断',
'乾旦' => '乾旦',
'乾曜' => '乾曜',
'乾清宮' => '乾清宫',
'乾盛世' => '乾盛世',
'乾紅' => '乾红',
'乾綱' => '乾纲',
'乾縣' => '乾县',
'乾象' => '乾象',
'乾造' => '乾造',
'乾道' => '乾道',
'乾陵' => '乾陵',
'乾隆' => '乾隆',
'乾隆年間' => '乾隆年间',
'乾隆皇帝' => '乾隆皇帝',
'二噁英' => '二𫫇英',
'以免藉口' => '以免借口',
'以功覆過' => '以功复过',
'侔德覆載' => '侔德复载',
'傢俱' => '家具',
'傷亡枕藉' => '伤亡枕藉',
'八濛山' => '八濛山',
'凌藉' => '凌借',
'出醜狼藉' => '出丑狼藉',
'函覆' => '函复',
'千鍾粟' => '千锺粟',
'反反覆覆' => '反反复复',
'反覆' => '反复',
'反覆思維' => '反复思维',
'反覆思量' => '反复思量',
'反覆性' => '反复性',
'名覆金甌' => '名复金瓯',
'哪吒' => '哪吒',
'回覆' => '回复',
'壺裏乾坤' => '壶里乾坤',
'大目乾連冥間救母變文' => '大目乾连冥间救母变文',
'宫商角徵羽' => '宫商角徵羽',
'射覆' => '射复',
'尼乾陀' => '尼乾陀',
'幺麼' => '幺麽',
'幺麼小丑' => '幺麽小丑',
'幺麼小醜' => '幺麽小丑',
'康乾' => '康乾',
'張法乾' => '张法乾',
'彷彿' => '仿佛',
'彷徨' => '彷徨',
'徵弦' => '徵弦',
'徵絃' => '徵弦',
'徵羽摩柯' => '徵羽摩柯',
'徵聲' => '徵声',
'徵調' => '徵调',
'徵音' => '徵音',
'情有獨鍾' => '情有独钟',
'憑藉' => '凭借',
'憑藉着' => '凭借着',
'手鍊' => '手链',
'扭轉乾坤' => '扭转乾坤',
'找藉口' => '找借口',
'拉鍊' => '拉链',
'拉鍊工程' => '拉链工程',
'拜覆' => '拜复',
'據瞭解' => '据了解',
'文錦覆阱' => '文锦复阱',
'於世成' => '於世成',
'於乎' => '於乎',
'於仲完' => '於仲完',
'於倫' => '於伦',
'於其一' => '於其一',
'於則' => '於则',
'於勇明' => '於勇明',
'於呼哀哉' => '於呼哀哉',
'於單' => '於单',
'於坦' => '於坦',
'於崇文' => '於崇文',
'於忠祥' => '於忠祥',
'於惟一' => '於惟一',
'於戲' => '於戏',
'於敖' => '於敖',
'於梨華' => '於梨华',
'於清言' => '於清言',
'於潛' => '於潜',
'於琳' => '於琳',
'於穆' => '於穆',
'於竹屋' => '於竹屋',
'於菟' => '於菟',
'於邑' => '於邑',
'於陵子' => '於陵子',
'旋乾轉坤' => '旋乾转坤',
'旋轉乾坤' => '旋转乾坤',
'旋轉乾坤之力' => '旋转乾坤之力',
'明瞭' => '明了',
'明覆' => '明复',
'書中自有千鍾粟' => '书中自有千锺粟',
'有序' => '有序',
'朝乾夕惕' => '朝乾夕惕',
'木吒' => '木吒',
'李乾德' => '李乾德',
'李澤鉅' => '李泽钜',
'李鍊福' => '李链福',
'李鍾郁' => '李锺郁',
'樊於期' => '樊於期',
'沈沒' => '沉没',
'沈沒成本' => '沉没成本',
'沈積' => '沉积',
'沈船' => '沉船',
'沈默' => '沉默',
'流徵' => '流徵',
'浪蕩乾坤' => '浪荡乾坤',
'滑藉' => '滑借',
'無序' => '无序',
'牴牾' => '抵牾',
'牴觸' => '抵触',
'狐藉虎威' => '狐借虎威',
'珍珠項鍊' => '珍珠项链',
'甚鉅' => '甚钜',
'申覆' => '申复',
'畢昇' => '毕昇',
'發覆' => '发复',
'瞭如' => '了如',
'瞭如指掌' => '了如指掌',
'瞭望' => '瞭望',
'瞭然' => '了然',
'瞭然於心' => '了然于心',
'瞭若指掌' => '了若指掌',
'瞭解' => '了解',
'瞭解到' => '了解到',
'示覆' => '示复',
'神祇' => '神祇',
'稟覆' => '禀复',
'竺乾' => '竺乾',
'答覆' => '答复',
'篤麼' => '笃麽',
'簡單明瞭' => '简单明了',
'籌畫' => '筹划',
'素藉' => '素借',
'老態龍鍾' => '老态龙钟',
'肘手鍊足' => '肘手链足',
'茵藉' => '茵借',
'萬鍾' => '万锺',
'蒜薹' => '蒜薹',
'蕓薹' => '芸薹',
'蕩覆' => '荡复',
'蕭乾' => '萧乾',
'藉代' => '借代',
'藉以' => '借以',
'藉助' => '借助',
'藉助於' => '借助于',
'藉卉' => '借卉',
'藉口' => '借口',
'藉喻' => '借喻',
'藉寇兵' => '借寇兵',
'藉寇兵齎盜糧' => '借寇兵赍盗粮',
'藉手' => '借手',
'藉據' => '借据',
'藉故' => '借故',
'藉故推辭' => '借故推辞',
'藉方' => '借方',
'藉條' => '借条',
'藉槁' => '借槁',
'藉機' => '借机',
'藉此' => '借此',
'藉此機會' => '借此机会',
'藉甚' => '借甚',
'藉由' => '借由',
'藉着' => '借着',
'藉端' => '借端',
'藉端生事' => '借端生事',
'藉箸代籌' => '借箸代筹',
'藉草枕塊' => '借草枕块',
'藉藉' => '藉藉',
'藉藉无名' => '藉藉无名',
'藉詞' => '借词',
'藉讀' => '借读',
'藉資' => '借资',
'衹得' => '只得',
'衹見樹木' => '只见树木',
'衹見樹木不見森林' => '只见树木不见森林',
'袖裏乾坤' => '袖里乾坤',
'覆上' => '复上',
'覆住' => '复住',
'覆信' => '复信',
'覆冒' => '复冒',
'覆呈' => '复呈',
'覆命' => '复命',
'覆墓' => '复墓',
'覆宗' => '复宗',
'覆帳' => '复帐',
'覆幬' => '复帱',
'覆成' => '复成',
'覆按' => '复按',
'覆文' => '复文',
'覆杯' => '复杯',
'覆校' => '复校',
'覆瓿' => '复瓿',
'覆盂' => '复盂',
'覆盆' => '覆盆',
'覆盆子' => '覆盆子',
'覆盤' => '覆盘',
'覆育' => '复育',
'覆蕉尋鹿' => '复蕉寻鹿',
'覆逆' => '复逆',
'覆醢' => '复醢',
'覆醬瓿' => '复酱瓿',
'覆電' => '复电',
'覆露' => '复露',
'覆鹿尋蕉' => '复鹿寻蕉',
'覆鹿遺蕉' => '复鹿遗蕉',
'覆鼎' => '复鼎',
'見覆' => '见复',
'角徵' => '角徵',
'角徵羽' => '角徵羽',
'計畫' => '计划',
'變徵' => '变徵',
'變徵之聲' => '变徵之声',
'變徵之音' => '变徵之音',
'貂覆額' => '貂复额',
'買臣覆水' => '买臣复水',
'踅門瞭戶' => '踅门了户',
'躪藉' => '躏借',
'郭子乾' => '郭子乾',
'酒逢知己千鍾少' => '酒逢知己千锺少',
'酒逢知己千鍾少話不投機半句多' => '酒逢知己千锺少话不投机半句多',
'醞藉' => '酝借',
'重覆' => '重复',
'金吒' => '金吒',
'金鍊' => '金链',
'鈞覆' => '钧复',
'鉅子' => '钜子',
'鉅萬' => '钜万',
'鉅防' => '钜防',
'鉸鍊' => '铰链',
'銀鍊' => '银链',
'錢鍾書' => '钱锺书',
'鍊墜' => '链坠',
'鍊子' => '链子',
'鍊形' => '链形',
'鍊條' => '链条',
'鍊錘' => '链锤',
'鍊鎖' => '链锁',
'鍛鍾' => '锻锺',
'鍾繇' => '钟繇',
'鍾萬梅' => '锺万梅',
'鍾重發' => '锺重发',
'鍾鍛' => '锺锻',
'鍾馗' => '锺馗',
'鎖鍊' => '锁链',
'鐵鍊' => '铁链',
'鑽石項鍊' => '钻石项链',
'雁杳魚沈' => '雁杳鱼沉',
'雖覆能復' => '虽覆能复',
'電覆' => '电复',
'露覆' => '露复',
'項鍊' => '项链',
'頗覆' => '颇复',
'頸鍊' => '颈链',
'顛乾倒坤' => '颠乾倒坤',
'顛倒乾坤' => '颠倒乾坤',
'顧藉' => '顾借',
'麼些族' => '麽些族',
'黄鍾公' => '黄锺公',
'龍鍾' => '龙钟',
);

View File

@@ -0,0 +1,511 @@
<?php return array (
'PN結' => 'PN接面',
'SQL注入' => 'SQL隱碼攻擊',
'SQL注入攻擊' => 'SQL隱碼攻擊',
'U盤' => '隨身碟',
'三極管' => '三極體',
'下拉列表' => '下拉選單',
'並行計算' => '平行計算',
'中間件' => '中介軟體',
'串口' => '串列埠',
'串行' => '序列',
'串行端口' => '串列埠',
'主引導記錄' => '主開機記錄',
'主板' => '主機板',
'二極管' => '二極體',
'互聯網' => '網際網路',
'交互' => '互動',
'交互式' => '互動式',
'人工智能' => '人工智慧',
'代碼' => '程式碼',
'代碼頁' => '內碼表',
'以太網' => '乙太網',
'任務欄' => '工作列',
'任務管理器' => '工作管理員',
'仿真' => '模擬',
'位圖' => '點陣圖',
'低級' => '低階',
'便攜式' => '行動式',
'保存' => '儲存',
'信噪比' => '訊雜比',
'信息' => '資訊',
'信息安全' => '資訊保安',
'信息技術' => '資訊科技',
'信息論' => '資訊理論',
'信號' => '訊號',
'信道' => '通道',
'傳感' => '感測',
'像素' => '畫素',
'僞代碼' => '虛擬碼',
'優先級' => '優先順序',
'優化' => '最佳化',
'元數據' => '後設資料',
'元編程' => '超程式設計',
'光標' => '游標',
'光盤' => '光碟',
'光驅' => '光碟機',
'免提' => '擴音',
'內存' => '記憶體',
'內核' => '核心',
'內置' => '內建',
'內聯函數' => '行內函數',
'全局' => '全域性',
'全角' => '全形',
'兼容' => '相容',
'冒泡排序' => '氣泡排序',
'函數' => '函式',
'函數式編程' => '函數語言程式設計',
'刀片服務器' => '刀鋒伺服器',
'分佈式' => '分散式',
'分區' => '分割槽',
'分辨率' => '解析度',
'刷新' => '重新整理',
'刻錄' => '燒錄',
'前綴' => '字首',
'剪切' => '剪下',
'剪貼板' => '剪貼簿',
'創建' => '建立',
'加載' => '載入',
'半角' => '半形',
'博客' => '部落格',
'卸載' => '解除安裝',
'原代碼' => '原始碼',
'參數' => '引數',
'參數表' => '參數列',
'句柄' => '控制代碼',
'可視化' => '視覺化',
'呼出' => '撥出',
'呼叫轉移' => '來電轉駁',
'命令式編程' => '指令式程式設計',
'命令行' => '命令列',
'命名空間' => '名稱空間',
'哈希' => '雜湊',
'單片機' => '微控制器',
'回調' => '回撥',
'固件' => '韌體',
'圖像' => '影象',
'圖庫' => '相簿',
'圖標' => '圖示',
'在線' => '線上',
'地址' => '地址',
'地址欄' => '位址列',
'城域網' => '都會網路',
'堆棧' => '堆疊',
'場效應管' => '場效電晶體',
'壁紙' => '桌布',
'外置' => '外接',
'外鍵' => '外來鍵',
'多任務' => '多工',
'多態' => '多型',
'多線程' => '多執行緒',
'字庫' => '字型檔',
'字段' => '欄位',
'字符' => '字元',
'字符串' => '字串',
'字符集' => '字符集',
'字節' => '位元組',
'字體' => '字型',
'存儲' => '儲存',
'存盤' => '存檔',
'宏' => '宏',
'宏內核' => '單核心',
'寄存器' => '暫存器',
'密鑰' => '金鑰',
'實例' => '例項',
'實模式' => '真實模式',
'審覈' => '稽覈',
'寫保護' => '防寫',
'寬帶' => '寬頻',
'尋址' => '定址',
'對話框' => '對話方塊',
'對象' => '物件',
'導入' => '匯入',
'導出' => '匯出',
'局域網' => '區域網',
'局部' => '區域性',
'屏幕' => '螢幕',
'屏蔽' => '遮蔽',
'嵌套' => '巢狀',
'布爾' => '布林',
'帶寬' => '頻寬',
'引導程序' => '載入程式',
'彙編' => '彙編',
'彙編語言' => '組合語言',
'後綴' => '字尾',
'循環' => '迴圈',
'性價比' => '價效比',
'性能' => '效能',
'截取' => '擷取',
'截屏' => '截圖',
'打印' => '列印',
'打印機' => '印表機',
'打開' => '開啟',
'批量' => '批次',
'拋出' => '丟擲',
'拷貝' => '複製',
'持久性' => '永續性',
'指針' => '指標',
'捲積' => '摺積',
'掃描儀' => '掃描器',
'掛斷' => '結束通話',
'採樣' => '取樣',
'採樣率' => '取樣率',
'接口' => '介面',
'控件' => '控制元件',
'插件' => '外掛',
'搜索' => '搜尋',
'操作數' => '運算元',
'操作符' => '運算子',
'操作系統' => '作業系統',
'擴展' => '擴充套件',
'擴展名' => '副檔名',
'支持' => '支援',
'支持者' => '支持者',
'散列' => '雜湊',
'數字' => '數字',
'數字印刷' => '數位印刷',
'數字電子' => '數位電子',
'數字電路' => '數位電路',
'數據' => '資料',
'數據倉庫' => '資料倉儲',
'數據報' => '資料包',
'數據庫' => '資料庫',
'數據挖掘' => '資料探勘',
'數據源' => '資料來源',
'數組' => '陣列',
'文件' => '檔案',
'文件名' => '檔名',
'文件夾' => '資料夾',
'文件擴展名' => '副檔名',
'文字處理' => '文書處理',
'文本' => '文字',
'文檔' => '文件',
'映射' => '對映',
'時分多址' => '分時多重進接',
'時分複用' => '分時多工',
'時鐘頻率' => '時脈頻率',
'晶閘管' => '閘流體',
'晶體管' => '電晶體',
'智能' => '智慧',
'最終用戶' => '終端使用者',
'有損壓縮' => '有失真壓縮',
'服務器' => '伺服器',
'本地代碼' => '原生代碼',
'析構函數' => '解構函式',
'枚舉' => '列舉',
'查找' => '查詢',
'查看' => '檢視',
'桌面型' => '桌上型',
'構造函數' => '建構函式',
'標識符' => '識別符號',
'模塊' => '模組',
'模擬' => '模擬',
'模擬電子' => '類比電子',
'模擬電路' => '類比電路',
'權限' => '許可權',
'正則表達式' => '正規表示式',
'死機' => '宕機',
'殺毒' => '防毒',
'比特' => '位元',
'比特幣' => '比特幣',
'比特率' => '位元率',
'波分複用' => '波長分波多工',
'消息' => '訊息',
'添加' => '新增',
'源代碼' => '原始碼',
'源文件' => '原始檔',
'源碼' => '原始碼',
'溢出' => '溢位',
'滾動條' => '捲軸',
'演示文稿' => '簡報',
'激光' => '鐳射',
'激活' => '啟用',
'無損壓縮' => '無失真壓縮',
'物理內存' => '實體記憶體',
'物理地址' => '實體地址',
'狀態欄' => '狀態列',
'用戶' => '使用者',
'用戶名' => '使用者名稱',
'界面' => '介面',
'異步' => '非同步',
'登錄' => '登入',
'發佈' => '釋出',
'發送' => '傳送',
'盤片' => '碟片',
'盤符' => '磁碟機代號',
'目標代碼' => '目的碼',
'相冊' => '相簿',
'矢量' => '向量',
'知識產權' => '智慧財產權',
'短信' => '簡訊',
'硬件' => '硬體',
'硬盤' => '硬碟',
'碼分多址' => '分碼多重進接',
'碼率' => '位元速率',
'磁盤' => '磁碟',
'磁道' => '磁軌',
'社區' => '社羣',
'移動硬盤' => '行動硬碟',
'移動網絡' => '行動網路',
'移動資料' => '行動資料',
'移動通信' => '行動通訊',
'移動電話' => '行動電話',
'程序' => '程式',
'程序員' => '程式設計師',
'空分多址' => '分空間多重進接',
'空分複用' => '空間多工',
'窗口' => '視窗',
'端口' => '埠',
'筆記本電腦' => '膝上型電腦',
'算子' => '運算元',
'算法' => '演算法',
'範式' => '正規化',
'粘貼' => '貼上',
'紅心大戰' => '傷心小棧',
'組件' => '元件',
'綁定' => '繫結',
'網上鄰居' => '網路上的芳鄰',
'網卡' => '網絡卡',
'網吧' => '網咖',
'網絡' => '網路',
'網關' => '閘道器',
'線程' => '執行緒',
'編程' => '程式設計',
'編程語言' => '程式語言',
'緩存' => '快取',
'縮略圖' => '縮圖',
'縮進' => '縮排',
'總線' => '匯流排',
'缺省' => '預設',
'聯繫' => '聯絡',
'聯繫歷史' => '通話記錄',
'聲卡' => '音效卡',
'聲明' => '宣告',
'脫機' => '離線',
'腳本' => '指令碼',
'自動轉屏' => '自動旋轉螢幕',
'臺式機' => '桌上型電腦',
'航天飛機' => '太空梭',
'芯片' => '晶片',
'花屏' => '破圖',
'菜單' => '選單',
'萬維網' => '全球資訊網',
'藍屏' => '藍色畫面',
'藍牙' => '藍芽',
'虛函數' => '虛擬函式',
'虛擬機' => '虛擬機器',
'虛擬機器' => '虛擬機器',
'表達式' => '表示式',
'複印' => '影印',
'複選按鈕' => '覈取按鈕',
'複選框' => '覈取方塊',
'視圖' => '檢視',
'視頻' => '影片',
'視頻會議' => '視訊會議',
'視頻通話' => '視訊通話',
'解釋器' => '直譯器',
'觸摸' => '觸控',
'觸摸屏' => '觸控式螢幕',
'計算機安全' => '電腦保安',
'計算機科學' => '電腦科學',
'訪問' => '訪問',
'設備' => '裝置',
'設置' => '設定',
'註冊機' => '序號產生器',
'註冊表' => '登錄檔',
'註銷' => '登出',
'調制' => '調變',
'調度' => '排程',
'調用' => '呼叫',
'調色板' => '調色盤',
'調製解調器' => '數據機',
'調試' => '除錯',
'調試器' => '偵錯程式',
'變量' => '變數',
'軟件' => '軟體',
'軟驅' => '軟碟機',
'轉義字符' => '跳脫字元',
'通信' => '通訊',
'通訊卡' => '通話卡',
'通配符' => '萬用字元',
'連接' => '連線',
'連接器' => '聯結器',
'進制' => '進位制',
'進程' => '程序',
'運算符' => '運算子',
'運行' => '執行',
'過程式編程' => '程序式程式設計',
'遞歸' => '遞迴',
'遠程' => '遠端',
'適配器' => '介面卡',
'邏輯門' => '邏輯閘',
'重命名' => '重新命名',
'重裝' => '重灌',
'重載' => '過載',
'金屬氧化物半導體' => '金氧半導體',
'錄像' => '錄影',
'鏈接' => '連結',
'鏈表' => '連結串列',
'鏡像' => '映象',
'門戶網站' => '入口網站',
'門電路' => '閘電路',
'閃存' => '快閃記憶體',
'關係數據庫' => '關聯式資料庫',
'隊列' => '佇列',
'集成' => '整合',
'集成電路' => '積體電路',
'集羣' => '叢集',
'雲存儲' => '雲端儲存',
'雲計算' => '雲端計算',
'面向對象' => '物件導向',
'面向過程' => '程序導向',
'音頻' => '音訊',
'頁眉' => '頁首',
'頁腳' => '頁尾',
'項目' => '專案',
'預處理器' => '前處理器',
'頭文件' => '標頭檔案',
'頻分多址' => '分頻多重進接',
'頻分複用' => '分頻多工',
'類型' => '型別',
'類模板' => '類别範本',
'顯像管' => '映象管',
'顯卡' => '顯示卡',
'顯存' => '視訊記憶體',
'飛行模式' => '飛航模式',
'首席信息官' => '資訊長',
'首席執行官' => '執行長',
'首席技術官' => '技術長',
'首席運營官' => '營運長',
'高性能計算' => '高效能運算',
'高清' => '高畫質',
'高端' => '高階',
'高級' => '高階',
'高速緩存' => '快取記憶體',
'黑客' => '駭客',
'默認' => '預設',
'默認值' => '預設值',
'點擊' => '點選',
'鼠標' => '滑鼠',
'乍得' => '查德',
'也門' => '葉門',
'仙童半導體' => '快捷半導體',
'伯利茲' => '貝里斯',
'佛得角' => '維德角',
'傅里葉' => '傅立葉',
'克羅地亞' => '克羅埃西亞',
'列支敦士登' => '列支敦斯登',
'利比里亞' => '賴比瑞亞',
'加納' => '迦納',
'加蓬' => '加彭',
'博茨瓦納' => '波札那',
'卡塔爾' => '卡達',
'危地馬拉' => '瓜地馬拉',
'厄瓜多爾' => '厄瓜多',
'厄立特里亞' => '厄利垂亞',
'吉布堤' => '吉布地',
'哈薩克斯坦' => '哈薩克',
'哥斯達黎加' => '哥斯大黎加',
'喫茶小舖' => '喫茶小舖',
'圖瓦盧' => '吐瓦魯',
'土庫曼斯坦' => '土庫曼',
'圭亞那' => '蓋亞那',
'坦桑尼亞' => '坦尚尼亞',
'埃塞俄比亞' => '衣索比亞',
'基里巴斯' => '吉里巴斯',
'塔吉克斯坦' => '塔吉克',
'塞拉利昂' => '獅子山',
'塞浦路斯' => '塞普勒斯',
'塞舌爾' => '塞席爾',
'多米尼加' => '多明尼加',
'安提瓜和巴布達' => '安地卡及巴布達',
'尼日利亞' => '奈及利亞',
'尼日爾' => '尼日',
'岡比亞' => '甘比亞',
'巴巴多斯' => '巴貝多',
'巴布亞新幾內亞' => '巴布亞紐幾內亞',
'布基納法索' => '布吉納法索',
'布隆迪' => '蒲隆地',
'帕勞' => '帛琉',
'幾內亞比紹' => '幾內亞比索',
'意大利' => '義大利',
'所羅門羣島' => '索羅門羣島',
'文萊' => '汶萊',
'斯威士蘭' => '史瓦濟蘭',
'斯洛文尼亞' => '斯洛維尼亞',
'新西蘭' => '紐西蘭',
'格林納達' => '格瑞那達',
'格魯吉亞' => '喬治亞',
'歐拉' => '尤拉',
'毛里塔尼亞' => '茅利塔尼亞',
'毛里求斯' => '模里西斯',
'沙特阿拉伯' => '沙烏地阿拉伯',
'波斯尼亞黑塞哥維那' => '波士尼亞赫塞哥維納',
'津巴布韋' => '辛巴威',
'洪都拉斯' => '宏都拉斯',
'溫納圖萬' => '那杜',
'烏茲別克斯坦' => '烏茲別克',
'特立尼達和多巴哥' => '千里達及托巴哥',
'瑙魯' => '諾魯',
'瓦努阿圖' => '萬那杜',
'盧旺達' => '盧安達',
'科摩羅' => '葛摩',
'科特迪瓦' => '象牙海岸',
'突尼斯' => '突尼西亞',
'純喫茶' => '純喫茶',
'索馬里' => '索馬利亞',
'老撾' => '寮國',
'聖基茨和尼維斯' => '聖克里斯多福及尼維斯',
'聖文森特和格林納丁斯' => '聖文森及格瑞那丁',
'聖盧西亞' => '聖露西亞',
'聖馬力諾' => '聖馬利諾',
'肯尼亞' => '肯亞',
'莫桑比克' => '莫三比克',
'萊索托' => '賴索托',
'萬象' => '永珍',
'蘇里南' => '蘇利南',
'貝寧' => '貝南',
'贊比亞' => '尚比亞',
'阿塞拜疆' => '亞塞拜然',
'阿拉伯聯合酋長國' => '阿拉伯聯合大公國',
'香農' => '夏農',
'馬爾代夫' => '馬爾地夫',
'馬里共和國' => '馬利共和國',
'元音' => '母音',
'冰棍' => '冰棒',
'出租車' => '計程車',
'咖喱' => '咖哩',
'塑料' => '塑膠',
'奔馳' => '賓士',
'奶酪' => '乳酪',
'幾率' => '機率',
'方便麪' => '泡麵',
'李彥宏' => '李彥宏',
'概率' => '機率',
'海內存知己' => '海內存知己',
'涼菜' => '冷盤',
'的士' => '計程車',
'砹' => '砈',
'硅' => '矽',
'程序不正義' => '程序不正義',
'程序正義' => '程序正義',
'空氣淨化器' => '空氣清淨機',
'納米' => '奈米',
'自行車' => '腳踏車',
'詞組' => '片語',
'蹦極' => '高空彈跳',
'輔音' => '子音',
'通過' => '透過',
'酰' => '醯',
'鈁' => '鍅',
'鈈' => '鈽',
'錇' => '鉳',
'鍀' => '鎝',
'鎄' => '鑀',
'鎇' => '鋂',
'鎿' => '錼',
'鐦' => '鉲',
'鑥' => '鎦',
'黃宏' => '黃宏',
'借記卡' => '簽帳金融卡',
);

View File

@@ -0,0 +1,390 @@
<?php return array (
'PN結' => 'PN接面',
'SQL注入' => 'SQL隱碼攻擊',
'SQL注入攻擊' => 'SQL隱碼攻擊',
'U盤' => '隨身碟',
'三極管' => '三極體',
'下拉列表' => '下拉選單',
'並行計算' => '平行計算',
'中間件' => '中介軟體',
'串口' => '串列埠',
'串行' => '序列',
'串行端口' => '串列埠',
'主引導記錄' => '主開機記錄',
'主板' => '主機板',
'二極管' => '二極體',
'互聯網' => '網際網路',
'交互' => '互動',
'交互式' => '互動式',
'人工智能' => '人工智慧',
'代碼' => '程式碼',
'代碼頁' => '內碼表',
'以太網' => '乙太網',
'任務欄' => '工作列',
'任務管理器' => '工作管理員',
'仿真' => '模擬',
'位圖' => '點陣圖',
'低級' => '低階',
'便攜式' => '行動式',
'保存' => '儲存',
'信噪比' => '訊雜比',
'信息' => '資訊',
'信息安全' => '資訊保安',
'信息技術' => '資訊科技',
'信息論' => '資訊理論',
'信號' => '訊號',
'信道' => '通道',
'傳感' => '感測',
'像素' => '畫素',
'僞代碼' => '虛擬碼',
'優先級' => '優先順序',
'優化' => '最佳化',
'元數據' => '後設資料',
'元編程' => '超程式設計',
'光標' => '游標',
'光盤' => '光碟',
'光驅' => '光碟機',
'免提' => '擴音',
'內存' => '記憶體',
'內核' => '核心',
'內置' => '內建',
'內聯函數' => '行內函數',
'全局' => '全域性',
'全角' => '全形',
'兼容' => '相容',
'冒泡排序' => '氣泡排序',
'函數' => '函式',
'函數式編程' => '函數語言程式設計',
'刀片服務器' => '刀鋒伺服器',
'分佈式' => '分散式',
'分區' => '分割槽',
'分辨率' => '解析度',
'刷新' => '重新整理',
'刻錄' => '燒錄',
'前綴' => '字首',
'剪切' => '剪下',
'剪貼板' => '剪貼簿',
'創建' => '建立',
'加載' => '載入',
'半角' => '半形',
'博客' => '部落格',
'卸載' => '解除安裝',
'原代碼' => '原始碼',
'參數' => '引數',
'參數表' => '參數列',
'句柄' => '控制代碼',
'可視化' => '視覺化',
'呼出' => '撥出',
'呼叫轉移' => '來電轉駁',
'命令式編程' => '指令式程式設計',
'命令行' => '命令列',
'命名空間' => '名稱空間',
'哈希' => '雜湊',
'單片機' => '微控制器',
'回調' => '回撥',
'固件' => '韌體',
'圖像' => '影象',
'圖庫' => '相簿',
'圖標' => '圖示',
'在線' => '線上',
'地址' => '地址',
'地址欄' => '位址列',
'城域網' => '都會網路',
'堆棧' => '堆疊',
'場效應管' => '場效電晶體',
'壁紙' => '桌布',
'外置' => '外接',
'外鍵' => '外來鍵',
'多任務' => '多工',
'多態' => '多型',
'多線程' => '多執行緒',
'字庫' => '字型檔',
'字段' => '欄位',
'字符' => '字元',
'字符串' => '字串',
'字符集' => '字符集',
'字節' => '位元組',
'字體' => '字型',
'存儲' => '儲存',
'存盤' => '存檔',
'宏' => '宏',
'宏內核' => '單核心',
'寄存器' => '暫存器',
'密鑰' => '金鑰',
'實例' => '例項',
'實模式' => '真實模式',
'審覈' => '稽覈',
'寫保護' => '防寫',
'寬帶' => '寬頻',
'尋址' => '定址',
'對話框' => '對話方塊',
'對象' => '物件',
'導入' => '匯入',
'導出' => '匯出',
'局域網' => '區域網',
'局部' => '區域性',
'屏幕' => '螢幕',
'屏蔽' => '遮蔽',
'嵌套' => '巢狀',
'布爾' => '布林',
'帶寬' => '頻寬',
'引導程序' => '載入程式',
'彙編' => '彙編',
'彙編語言' => '組合語言',
'後綴' => '字尾',
'循環' => '迴圈',
'性價比' => '價效比',
'性能' => '效能',
'截取' => '擷取',
'截屏' => '截圖',
'打印' => '列印',
'打印機' => '印表機',
'打開' => '開啟',
'批量' => '批次',
'拋出' => '丟擲',
'拷貝' => '複製',
'持久性' => '永續性',
'指針' => '指標',
'捲積' => '摺積',
'掃描儀' => '掃描器',
'掛斷' => '結束通話',
'採樣' => '取樣',
'採樣率' => '取樣率',
'接口' => '介面',
'控件' => '控制元件',
'插件' => '外掛',
'搜索' => '搜尋',
'操作數' => '運算元',
'操作符' => '運算子',
'操作系統' => '作業系統',
'擴展' => '擴充套件',
'擴展名' => '副檔名',
'支持' => '支援',
'支持者' => '支持者',
'散列' => '雜湊',
'數字' => '數字',
'數字印刷' => '數位印刷',
'數字電子' => '數位電子',
'數字電路' => '數位電路',
'數據' => '資料',
'數據倉庫' => '資料倉儲',
'數據報' => '資料包',
'數據庫' => '資料庫',
'數據挖掘' => '資料探勘',
'數據源' => '資料來源',
'數組' => '陣列',
'文件' => '檔案',
'文件名' => '檔名',
'文件夾' => '資料夾',
'文件擴展名' => '副檔名',
'文字處理' => '文書處理',
'文本' => '文字',
'文檔' => '文件',
'映射' => '對映',
'時分多址' => '分時多重進接',
'時分複用' => '分時多工',
'時鐘頻率' => '時脈頻率',
'晶閘管' => '閘流體',
'晶體管' => '電晶體',
'智能' => '智慧',
'最終用戶' => '終端使用者',
'有損壓縮' => '有失真壓縮',
'服務器' => '伺服器',
'本地代碼' => '原生代碼',
'析構函數' => '解構函式',
'枚舉' => '列舉',
'查找' => '查詢',
'查看' => '檢視',
'桌面型' => '桌上型',
'構造函數' => '建構函式',
'標識符' => '識別符號',
'模塊' => '模組',
'模擬' => '模擬',
'模擬電子' => '類比電子',
'模擬電路' => '類比電路',
'權限' => '許可權',
'正則表達式' => '正規表示式',
'死機' => '宕機',
'殺毒' => '防毒',
'比特' => '位元',
'比特幣' => '比特幣',
'比特率' => '位元率',
'波分複用' => '波長分波多工',
'消息' => '訊息',
'添加' => '新增',
'源代碼' => '原始碼',
'源文件' => '原始檔',
'源碼' => '原始碼',
'溢出' => '溢位',
'滾動條' => '捲軸',
'演示文稿' => '簡報',
'激光' => '鐳射',
'激活' => '啟用',
'無損壓縮' => '無失真壓縮',
'物理內存' => '實體記憶體',
'物理地址' => '實體地址',
'狀態欄' => '狀態列',
'用戶' => '使用者',
'用戶名' => '使用者名稱',
'界面' => '介面',
'異步' => '非同步',
'登錄' => '登入',
'發佈' => '釋出',
'發送' => '傳送',
'盤片' => '碟片',
'盤符' => '磁碟機代號',
'目標代碼' => '目的碼',
'相冊' => '相簿',
'矢量' => '向量',
'知識產權' => '智慧財產權',
'短信' => '簡訊',
'硬件' => '硬體',
'硬盤' => '硬碟',
'碼分多址' => '分碼多重進接',
'碼率' => '位元速率',
'磁盤' => '磁碟',
'磁道' => '磁軌',
'社區' => '社羣',
'移動硬盤' => '行動硬碟',
'移動網絡' => '行動網路',
'移動資料' => '行動資料',
'移動通信' => '行動通訊',
'移動電話' => '行動電話',
'程序' => '程式',
'程序員' => '程式設計師',
'空分多址' => '分空間多重進接',
'空分複用' => '空間多工',
'窗口' => '視窗',
'端口' => '埠',
'筆記本電腦' => '膝上型電腦',
'算子' => '運算元',
'算法' => '演算法',
'範式' => '正規化',
'粘貼' => '貼上',
'紅心大戰' => '傷心小棧',
'組件' => '元件',
'綁定' => '繫結',
'網上鄰居' => '網路上的芳鄰',
'網卡' => '網絡卡',
'網吧' => '網咖',
'網絡' => '網路',
'網關' => '閘道器',
'線程' => '執行緒',
'編程' => '程式設計',
'編程語言' => '程式語言',
'緩存' => '快取',
'縮略圖' => '縮圖',
'縮進' => '縮排',
'總線' => '匯流排',
'缺省' => '預設',
'聯繫' => '聯絡',
'聯繫歷史' => '通話記錄',
'聲卡' => '音效卡',
'聲明' => '宣告',
'脫機' => '離線',
'腳本' => '指令碼',
'自動轉屏' => '自動旋轉螢幕',
'臺式機' => '桌上型電腦',
'航天飛機' => '太空梭',
'芯片' => '晶片',
'花屏' => '破圖',
'菜單' => '選單',
'萬維網' => '全球資訊網',
'藍屏' => '藍色畫面',
'藍牙' => '藍芽',
'虛函數' => '虛擬函式',
'虛擬機' => '虛擬機器',
'虛擬機器' => '虛擬機器',
'表達式' => '表示式',
'複印' => '影印',
'複選按鈕' => '覈取按鈕',
'複選框' => '覈取方塊',
'視圖' => '檢視',
'視頻' => '影片',
'視頻會議' => '視訊會議',
'視頻通話' => '視訊通話',
'解釋器' => '直譯器',
'觸摸' => '觸控',
'觸摸屏' => '觸控式螢幕',
'計算機安全' => '電腦保安',
'計算機科學' => '電腦科學',
'訪問' => '訪問',
'設備' => '裝置',
'設置' => '設定',
'註冊機' => '序號產生器',
'註冊表' => '登錄檔',
'註銷' => '登出',
'調制' => '調變',
'調度' => '排程',
'調用' => '呼叫',
'調色板' => '調色盤',
'調製解調器' => '數據機',
'調試' => '除錯',
'調試器' => '偵錯程式',
'變量' => '變數',
'軟件' => '軟體',
'軟驅' => '軟碟機',
'轉義字符' => '跳脫字元',
'通信' => '通訊',
'通訊卡' => '通話卡',
'通配符' => '萬用字元',
'連接' => '連線',
'連接器' => '聯結器',
'進制' => '進位制',
'進程' => '程序',
'運算符' => '運算子',
'運行' => '執行',
'過程式編程' => '程序式程式設計',
'遞歸' => '遞迴',
'遠程' => '遠端',
'適配器' => '介面卡',
'邏輯門' => '邏輯閘',
'重命名' => '重新命名',
'重裝' => '重灌',
'重載' => '過載',
'金屬氧化物半導體' => '金氧半導體',
'錄像' => '錄影',
'鏈接' => '連結',
'鏈表' => '連結串列',
'鏡像' => '映象',
'門戶網站' => '入口網站',
'門電路' => '閘電路',
'閃存' => '快閃記憶體',
'關係數據庫' => '關聯式資料庫',
'隊列' => '佇列',
'集成' => '整合',
'集成電路' => '積體電路',
'集羣' => '叢集',
'雲存儲' => '雲端儲存',
'雲計算' => '雲端計算',
'面向對象' => '物件導向',
'面向過程' => '程序導向',
'音頻' => '音訊',
'頁眉' => '頁首',
'頁腳' => '頁尾',
'項目' => '專案',
'預處理器' => '前處理器',
'頭文件' => '標頭檔案',
'頻分多址' => '分頻多重進接',
'頻分複用' => '分頻多工',
'類型' => '型別',
'類模板' => '類别範本',
'顯像管' => '映象管',
'顯卡' => '顯示卡',
'顯存' => '視訊記憶體',
'飛行模式' => '飛航模式',
'首席信息官' => '資訊長',
'首席執行官' => '執行長',
'首席技術官' => '技術長',
'首席運營官' => '營運長',
'高性能計算' => '高效能運算',
'高清' => '高畫質',
'高端' => '高階',
'高級' => '高階',
'高速緩存' => '快取記憶體',
'黑客' => '駭客',
'默認' => '預設',
'默認值' => '預設值',
'點擊' => '點選',
'鼠標' => '滑鼠',
);

View File

@@ -0,0 +1,86 @@
<?php return array (
'乍得' => '查德',
'也門' => '葉門',
'仙童半導體' => '快捷半導體',
'伯利茲' => '貝里斯',
'佛得角' => '維德角',
'傅里葉' => '傅立葉',
'克羅地亞' => '克羅埃西亞',
'列支敦士登' => '列支敦斯登',
'利比里亞' => '賴比瑞亞',
'加納' => '迦納',
'加蓬' => '加彭',
'博茨瓦納' => '波札那',
'卡塔爾' => '卡達',
'危地馬拉' => '瓜地馬拉',
'厄瓜多爾' => '厄瓜多',
'厄立特里亞' => '厄利垂亞',
'吉布堤' => '吉布地',
'哈薩克斯坦' => '哈薩克',
'哥斯達黎加' => '哥斯大黎加',
'喫茶小舖' => '喫茶小舖',
'圖瓦盧' => '吐瓦魯',
'土庫曼斯坦' => '土庫曼',
'圭亞那' => '蓋亞那',
'坦桑尼亞' => '坦尚尼亞',
'埃塞俄比亞' => '衣索比亞',
'基里巴斯' => '吉里巴斯',
'塔吉克斯坦' => '塔吉克',
'塞拉利昂' => '獅子山',
'塞浦路斯' => '塞普勒斯',
'塞舌爾' => '塞席爾',
'多米尼加' => '多明尼加',
'安提瓜和巴布達' => '安地卡及巴布達',
'尼日利亞' => '奈及利亞',
'尼日爾' => '尼日',
'岡比亞' => '甘比亞',
'巴巴多斯' => '巴貝多',
'巴布亞新幾內亞' => '巴布亞紐幾內亞',
'布基納法索' => '布吉納法索',
'布隆迪' => '蒲隆地',
'帕勞' => '帛琉',
'幾內亞比紹' => '幾內亞比索',
'意大利' => '義大利',
'所羅門羣島' => '索羅門羣島',
'文萊' => '汶萊',
'斯威士蘭' => '史瓦濟蘭',
'斯洛文尼亞' => '斯洛維尼亞',
'新西蘭' => '紐西蘭',
'格林納達' => '格瑞那達',
'格魯吉亞' => '喬治亞',
'歐拉' => '尤拉',
'毛里塔尼亞' => '茅利塔尼亞',
'毛里求斯' => '模里西斯',
'沙特阿拉伯' => '沙烏地阿拉伯',
'波斯尼亞黑塞哥維那' => '波士尼亞赫塞哥維納',
'津巴布韋' => '辛巴威',
'洪都拉斯' => '宏都拉斯',
'溫納圖萬' => '那杜',
'烏茲別克斯坦' => '烏茲別克',
'特立尼達和多巴哥' => '千里達及托巴哥',
'瑙魯' => '諾魯',
'瓦努阿圖' => '萬那杜',
'盧旺達' => '盧安達',
'科摩羅' => '葛摩',
'科特迪瓦' => '象牙海岸',
'突尼斯' => '突尼西亞',
'純喫茶' => '純喫茶',
'索馬里' => '索馬利亞',
'老撾' => '寮國',
'聖基茨和尼維斯' => '聖克里斯多福及尼維斯',
'聖文森特和格林納丁斯' => '聖文森及格瑞那丁',
'聖盧西亞' => '聖露西亞',
'聖馬力諾' => '聖馬利諾',
'肯尼亞' => '肯亞',
'莫桑比克' => '莫三比克',
'萊索托' => '賴索托',
'萬象' => '永珍',
'蘇里南' => '蘇利南',
'貝寧' => '貝南',
'贊比亞' => '尚比亞',
'阿塞拜疆' => '亞塞拜然',
'阿拉伯聯合酋長國' => '阿拉伯聯合大公國',
'香農' => '夏農',
'馬爾代夫' => '馬爾地夫',
'馬里共和國' => '馬利共和國',
);

View File

@@ -0,0 +1,39 @@
<?php return array (
'元音' => '母音',
'冰棍' => '冰棒',
'出租車' => '計程車',
'咖喱' => '咖哩',
'塑料' => '塑膠',
'奔馳' => '賓士',
'奶酪' => '乳酪',
'幾率' => '機率',
'方便麪' => '泡麵',
'李彥宏' => '李彥宏',
'概率' => '機率',
'海內存知己' => '海內存知己',
'涼菜' => '冷盤',
'的士' => '計程車',
'砹' => '砈',
'硅' => '矽',
'程序不正義' => '程序不正義',
'程序正義' => '程序正義',
'空氣淨化器' => '空氣清淨機',
'納米' => '奈米',
'自行車' => '腳踏車',
'詞組' => '片語',
'蹦極' => '高空彈跳',
'輔音' => '子音',
'通過' => '透過',
'酰' => '醯',
'鈁' => '鍅',
'鈈' => '鈽',
'錇' => '鉳',
'鍀' => '鎝',
'鎄' => '鑀',
'鎇' => '鋂',
'鎿' => '錼',
'鐦' => '鉲',
'鑥' => '鎦',
'黃宏' => '黃宏',
'借記卡' => '簽帳金融卡',
);

View File

@@ -0,0 +1,493 @@
<?php return array (
'PN接面' => 'PN結',
'SQL隱碼攻擊' => 'SQL注入攻擊',
'隨身碟' => 'U盤',
'三極體' => '三極管',
'下拉選單' => '下拉列表',
'平行計算' => '並行計算',
'中介軟體' => '中間件',
'串列埠' => '串行端口',
'序列' => '串行',
'主開機記錄' => '主引導記錄',
'主機板' => '主板',
'二極體' => '二極管',
'網際網路' => '互聯網',
'互動' => '交互',
'互動式' => '交互式',
'人工智慧' => '人工智能',
'程式碼' => '代碼',
'內碼表' => '代碼頁',
'乙太網' => '以太網',
'工作列' => '任務欄',
'工作管理員' => '任務管理器',
'模擬' => '模擬',
'點陣圖' => '位圖',
'低階' => '低級',
'行動式' => '便攜式',
'儲存' => '存儲',
'訊雜比' => '信噪比',
'資訊' => '信息',
'資訊保安' => '信息安全',
'資訊科技' => '信息技術',
'資訊理論' => '信息論',
'訊號' => '信號',
'通道' => '信道',
'感測' => '傳感',
'畫素' => '像素',
'虛擬碼' => '僞代碼',
'優先順序' => '優先級',
'最佳化' => '優化',
'後設資料' => '元數據',
'超程式設計' => '元編程',
'游標' => '光標',
'光碟' => '光盤',
'光碟機' => '光驅',
'擴音' => '免提',
'記憶體' => '內存',
'核心' => '內核',
'內建' => '內置',
'行內函數' => '內聯函數',
'全域性' => '全局',
'全形' => '全角',
'相容' => '兼容',
'氣泡排序' => '冒泡排序',
'函式' => '函數',
'函數語言程式設計' => '函數式編程',
'刀鋒伺服器' => '刀片服務器',
'分散式' => '分佈式',
'分割槽' => '分區',
'解析度' => '分辨率',
'重新整理' => '刷新',
'燒錄' => '刻錄',
'字首' => '前綴',
'剪下' => '剪切',
'剪貼簿' => '剪貼板',
'建立' => '創建',
'載入' => '加載',
'半形' => '半角',
'部落格' => '博客',
'解除安裝' => '卸載',
'原始碼' => '源碼',
'引數' => '參數',
'參數列' => '參數表',
'控制代碼' => '句柄',
'視覺化' => '可視化',
'撥出' => '呼出',
'來電轉駁' => '呼叫轉移',
'指令式程式設計' => '命令式編程',
'命令列' => '命令行',
'名稱空間' => '命名空間',
'雜湊' => '散列',
'微控制器' => '單片機',
'回撥' => '回調',
'韌體' => '固件',
'影象' => '圖像',
'相簿' => '相冊',
'圖示' => '圖標',
'線上' => '在線',
'地址' => '地址',
'位址列' => '地址欄',
'都會網路' => '城域網',
'堆疊' => '堆棧',
'場效電晶體' => '場效應管',
'桌布' => '壁紙',
'外接' => '外置',
'外來鍵' => '外鍵',
'多工' => '多任務',
'多型' => '多態',
'多執行緒' => '多線程',
'字型檔' => '字庫',
'欄位' => '字段',
'字元' => '字符',
'字串' => '字符串',
'字符集' => '字符集',
'位元組' => '字節',
'字型' => '字體',
'存檔' => '存盤',
'宏' => '宏',
'單核心' => '宏內核',
'暫存器' => '寄存器',
'金鑰' => '密鑰',
'例項' => '實例',
'真實模式' => '實模式',
'稽覈' => '審覈',
'防寫' => '寫保護',
'寬頻' => '寬帶',
'定址' => '尋址',
'對話方塊' => '對話框',
'物件' => '對象',
'匯入' => '導入',
'匯出' => '導出',
'區域網' => '局域網',
'區域性' => '局部',
'螢幕' => '屏幕',
'遮蔽' => '屏蔽',
'巢狀' => '嵌套',
'布林' => '布爾',
'頻寬' => '帶寬',
'載入程式' => '引導程序',
'彙編' => '彙編',
'組合語言' => '彙編語言',
'字尾' => '後綴',
'迴圈' => '循環',
'價效比' => '性價比',
'效能' => '性能',
'擷取' => '截取',
'截圖' => '截屏',
'列印' => '打印',
'印表機' => '打印機',
'開啟' => '打開',
'批次' => '批量',
'丟擲' => '拋出',
'複製' => '拷貝',
'永續性' => '持久性',
'指標' => '指針',
'摺積' => '捲積',
'掃描器' => '掃描儀',
'結束通話' => '掛斷',
'取樣' => '採樣',
'取樣率' => '採樣率',
'介面' => '界面',
'控制元件' => '控件',
'外掛' => '插件',
'搜尋' => '搜索',
'運算元' => '算子',
'運算子' => '運算符',
'作業系統' => '操作系統',
'擴充套件' => '擴展',
'副檔名' => '文件擴展名',
'支援' => '支持',
'支持者' => '支持者',
'數字' => '數字',
'數位印刷' => '數字印刷',
'數位電子' => '數字電子',
'數位電路' => '數字電路',
'資料' => '數據',
'資料倉儲' => '數據倉庫',
'資料包' => '數據報',
'資料庫' => '數據庫',
'資料探勘' => '數據挖掘',
'資料來源' => '數據源',
'陣列' => '數組',
'檔案' => '文件',
'檔名' => '文件名',
'資料夾' => '文件夾',
'文書處理' => '文字處理',
'文字' => '文本',
'文件' => '文檔',
'對映' => '映射',
'分時多重進接' => '時分多址',
'分時多工' => '時分複用',
'時脈頻率' => '時鐘頻率',
'閘流體' => '晶閘管',
'電晶體' => '晶體管',
'智慧' => '智能',
'終端使用者' => '最終用戶',
'有失真壓縮' => '有損壓縮',
'伺服器' => '服務器',
'原生代碼' => '本地代碼',
'解構函式' => '析構函數',
'列舉' => '枚舉',
'查詢' => '查找',
'檢視' => '視圖',
'桌上型' => '桌面型',
'建構函式' => '構造函數',
'識別符號' => '標識符',
'模組' => '模塊',
'類比電子' => '模擬電子',
'類比電路' => '模擬電路',
'許可權' => '權限',
'正規表示式' => '正則表達式',
'宕機' => '死機',
'防毒' => '殺毒',
'位元' => '比特',
'比特幣' => '比特幣',
'位元率' => '比特率',
'波長分波多工' => '波分複用',
'訊息' => '消息',
'新增' => '添加',
'原始檔' => '源文件',
'溢位' => '溢出',
'捲軸' => '滾動條',
'簡報' => '演示文稿',
'鐳射' => '激光',
'啟用' => '激活',
'無失真壓縮' => '無損壓縮',
'實體記憶體' => '物理內存',
'實體地址' => '物理地址',
'狀態列' => '狀態欄',
'使用者' => '用戶',
'使用者名稱' => '用戶名',
'非同步' => '異步',
'登入' => '登錄',
'釋出' => '發佈',
'傳送' => '發送',
'碟片' => '盤片',
'磁碟機代號' => '盤符',
'目的碼' => '目標代碼',
'向量' => '矢量',
'智慧財產權' => '知識產權',
'簡訊' => '短信',
'硬體' => '硬件',
'硬碟' => '硬盤',
'分碼多重進接' => '碼分多址',
'位元速率' => '碼率',
'磁碟' => '磁盤',
'磁軌' => '磁道',
'社羣' => '社區',
'行動硬碟' => '移動硬盤',
'行動網路' => '移動網絡',
'行動資料' => '移動資料',
'行動通訊' => '移動通信',
'行動電話' => '移動電話',
'程式' => '程序',
'程式設計師' => '程序員',
'分空間多重進接' => '空分多址',
'空間多工' => '空分複用',
'視窗' => '窗口',
'埠' => '端口',
'膝上型電腦' => '筆記本電腦',
'演算法' => '算法',
'正規化' => '範式',
'貼上' => '粘貼',
'傷心小棧' => '紅心大戰',
'元件' => '組件',
'繫結' => '綁定',
'網路上的芳鄰' => '網上鄰居',
'網絡卡' => '網卡',
'網咖' => '網吧',
'網路' => '網絡',
'閘道器' => '網關',
'執行緒' => '線程',
'程式設計' => '編程',
'程式語言' => '編程語言',
'快取' => '緩存',
'縮圖' => '縮略圖',
'縮排' => '縮進',
'匯流排' => '總線',
'預設' => '默認',
'聯絡' => '聯繫',
'通話記錄' => '聯繫歷史',
'音效卡' => '聲卡',
'宣告' => '聲明',
'離線' => '脫機',
'指令碼' => '腳本',
'自動旋轉螢幕' => '自動轉屏',
'桌上型電腦' => '臺式機',
'太空梭' => '航天飛機',
'晶片' => '芯片',
'破圖' => '花屏',
'選單' => '菜單',
'全球資訊網' => '萬維網',
'藍色畫面' => '藍屏',
'藍芽' => '藍牙',
'虛擬函式' => '虛函數',
'虛擬機器' => '虛擬機器',
'表示式' => '表達式',
'影印' => '複印',
'覈取按鈕' => '複選按鈕',
'覈取方塊' => '複選框',
'影片' => '視頻',
'視訊會議' => '視頻會議',
'視訊通話' => '視頻通話',
'直譯器' => '解釋器',
'觸控' => '觸摸',
'觸控式螢幕' => '觸摸屏',
'電腦保安' => '計算機安全',
'電腦科學' => '計算機科學',
'訪問' => '訪問',
'裝置' => '設備',
'設定' => '設置',
'序號產生器' => '註冊機',
'登錄檔' => '註冊表',
'登出' => '註銷',
'調變' => '調制',
'排程' => '調度',
'呼叫' => '調用',
'調色盤' => '調色板',
'數據機' => '調製解調器',
'除錯' => '調試',
'偵錯程式' => '調試器',
'變數' => '變量',
'軟體' => '軟件',
'軟碟機' => '軟驅',
'跳脫字元' => '轉義字符',
'通訊' => '通信',
'通話卡' => '通訊卡',
'萬用字元' => '通配符',
'連線' => '連接',
'聯結器' => '連接器',
'進位制' => '進制',
'程序' => '進程',
'執行' => '運行',
'程序式程式設計' => '過程式編程',
'遞迴' => '遞歸',
'遠端' => '遠程',
'介面卡' => '適配器',
'邏輯閘' => '邏輯門',
'重新命名' => '重命名',
'重灌' => '重裝',
'過載' => '重載',
'金氧半導體' => '金屬氧化物半導體',
'錄影' => '錄像',
'連結' => '鏈接',
'連結串列' => '鏈表',
'映象' => '鏡像',
'入口網站' => '門戶網站',
'閘電路' => '門電路',
'快閃記憶體' => '閃存',
'關聯式資料庫' => '關係數據庫',
'佇列' => '隊列',
'整合' => '集成',
'積體電路' => '集成電路',
'叢集' => '集羣',
'雲端儲存' => '雲存儲',
'雲端計算' => '雲計算',
'物件導向' => '面向對象',
'程序導向' => '面向過程',
'音訊' => '音頻',
'頁首' => '頁眉',
'頁尾' => '頁腳',
'專案' => '項目',
'前處理器' => '預處理器',
'標頭檔案' => '頭文件',
'分頻多重進接' => '頻分多址',
'分頻多工' => '頻分複用',
'型別' => '類型',
'類别範本' => '類模板',
'映象管' => '顯像管',
'顯示卡' => '顯卡',
'視訊記憶體' => '顯存',
'飛航模式' => '飛行模式',
'資訊長' => '首席信息官',
'執行長' => '首席執行官',
'技術長' => '首席技術官',
'營運長' => '首席運營官',
'高效能運算' => '高性能計算',
'高畫質' => '高清',
'高階' => '高級',
'快取記憶體' => '高速緩存',
'駭客' => '黑客',
'預設值' => '默認值',
'點選' => '點擊',
'滑鼠' => '鼠標',
'查德' => '乍得',
'葉門' => '也門',
'快捷半導體' => '仙童半導體',
'貝里斯' => '伯利茲',
'維德角' => '佛得角',
'傅立葉' => '傅里葉',
'克羅埃西亞' => '克羅地亞',
'列支敦斯登' => '列支敦士登',
'賴比瑞亞' => '利比里亞',
'迦納' => '加納',
'加彭' => '加蓬',
'波札那' => '博茨瓦納',
'卡達' => '卡塔爾',
'瓜地馬拉' => '危地馬拉',
'厄瓜多' => '厄瓜多爾',
'厄利垂亞' => '厄立特里亞',
'吉布地' => '吉布堤',
'哈薩克' => '哈薩克斯坦',
'哥斯大黎加' => '哥斯達黎加',
'喫茶小舖' => '喫茶小舖',
'吐瓦魯' => '圖瓦盧',
'土庫曼' => '土庫曼斯坦',
'蓋亞那' => '圭亞那',
'坦尚尼亞' => '坦桑尼亞',
'衣索比亞' => '埃塞俄比亞',
'吉里巴斯' => '基里巴斯',
'塔吉克' => '塔吉克斯坦',
'獅子山' => '塞拉利昂',
'塞普勒斯' => '塞浦路斯',
'塞席爾' => '塞舌爾',
'多明尼加' => '多米尼加',
'安地卡及巴布達' => '安提瓜和巴布達',
'奈及利亞' => '尼日利亞',
'尼日' => '尼日爾',
'甘比亞' => '岡比亞',
'巴貝多' => '巴巴多斯',
'巴布亞紐幾內亞' => '巴布亞新幾內亞',
'布吉納法索' => '布基納法索',
'蒲隆地' => '布隆迪',
'帛琉' => '帕勞',
'幾內亞比索' => '幾內亞比紹',
'義大利' => '意大利',
'索羅門羣島' => '所羅門羣島',
'汶萊' => '文萊',
'史瓦濟蘭' => '斯威士蘭',
'斯洛維尼亞' => '斯洛文尼亞',
'紐西蘭' => '新西蘭',
'格瑞那達' => '格林納達',
'喬治亞' => '格魯吉亞',
'尤拉' => '歐拉',
'茅利塔尼亞' => '毛里塔尼亞',
'模里西斯' => '毛里求斯',
'沙烏地阿拉伯' => '沙特阿拉伯',
'波士尼亞赫塞哥維納' => '波斯尼亞黑塞哥維那',
'辛巴威' => '津巴布韋',
'宏都拉斯' => '洪都拉斯',
'那杜' => '溫納圖萬',
'烏茲別克' => '烏茲別克斯坦',
'千里達及托巴哥' => '特立尼達和多巴哥',
'諾魯' => '瑙魯',
'萬那杜' => '瓦努阿圖',
'盧安達' => '盧旺達',
'葛摩' => '科摩羅',
'象牙海岸' => '科特迪瓦',
'突尼西亞' => '突尼斯',
'純喫茶' => '純喫茶',
'索馬利亞' => '索馬里',
'寮國' => '老撾',
'聖克里斯多福及尼維斯' => '聖基茨和尼維斯',
'聖文森及格瑞那丁' => '聖文森特和格林納丁斯',
'聖露西亞' => '聖盧西亞',
'聖馬利諾' => '聖馬力諾',
'肯亞' => '肯尼亞',
'莫三比克' => '莫桑比克',
'賴索托' => '萊索托',
'永珍' => '萬象',
'蘇利南' => '蘇里南',
'貝南' => '貝寧',
'尚比亞' => '贊比亞',
'亞塞拜然' => '阿塞拜疆',
'阿拉伯聯合大公國' => '阿拉伯聯合酋長國',
'夏農' => '香農',
'馬爾地夫' => '馬爾代夫',
'馬利共和國' => '馬里共和國',
'母音' => '元音',
'冰棒' => '冰棍',
'計程車' => '的士',
'咖哩' => '咖喱',
'塑膠' => '塑料',
'賓士' => '奔馳',
'乳酪' => '奶酪',
'機率' => '概率',
'泡麵' => '方便麪',
'李彥宏' => '李彥宏',
'海內存知己' => '海內存知己',
'冷盤' => '涼菜',
'砈' => '砹',
'矽' => '硅',
'程序不正義' => '程序不正義',
'程序正義' => '程序正義',
'空氣清淨機' => '空氣淨化器',
'奈米' => '納米',
'腳踏車' => '自行車',
'片語' => '詞組',
'高空彈跳' => '蹦極',
'子音' => '輔音',
'透過' => '通過',
'醯' => '酰',
'鍅' => '鈁',
'鈽' => '鈈',
'鉳' => '錇',
'鎝' => '鍀',
'鑀' => '鎄',
'鋂' => '鎇',
'錼' => '鎿',
'鉲' => '鐦',
'鎦' => '鑥',
'黃宏' => '黃宏',
'簽帳金融卡' => '借記卡',
);

View File

@@ -0,0 +1,41 @@
<?php return array (
'僞' => '偽',
'啓' => '啟',
'喫' => '吃',
'嫺' => '嫻',
'嬀' => '媯',
'峯' => '峰',
'幺' => '么',
'擡' => '抬',
'棱' => '稜',
'檐' => '簷',
'污' => '汙',
'泄' => '洩',
'潙' => '溈',
'潨' => '潀',
'爲' => '為',
'牀' => '床',
'痹' => '痺',
'癡' => '痴',
'皁' => '皂',
'着' => '著',
'睾' => '睪',
'祕' => '秘',
'竈' => '灶',
'糉' => '粽',
'繮' => '韁',
'纔' => '才',
'羣' => '群',
'脣' => '唇',
'蔘' => '參',
'蔿' => '蒍',
'衆' => '眾',
'裏' => '裡',
'覈' => '核',
'踊' => '踴',
'鉢' => '缽',
'鍼' => '針',
'鮎' => '鯰',
'麪' => '麵',
'齶' => '顎',
);

View File

@@ -0,0 +1,41 @@
<?php return array (
'偽' => '僞',
'啟' => '啓',
'吃' => '喫',
'嫻' => '嫺',
'媯' => '嬀',
'峰' => '峯',
'么' => '幺',
'抬' => '擡',
'稜' => '棱',
'簷' => '檐',
'汙' => '污',
'洩' => '泄',
'溈' => '潙',
'潀' => '潨',
'為' => '爲',
'床' => '牀',
'痺' => '痹',
'痴' => '癡',
'皂' => '皁',
'著' => '着',
'睪' => '睾',
'秘' => '祕',
'灶' => '竈',
'粽' => '糉',
'韁' => '繮',
'才' => '纔',
'群' => '羣',
'唇' => '脣',
'參' => '蔘',
'蒍' => '蔿',
'眾' => '衆',
'裡' => '裏',
'核' => '覈',
'踴' => '踊',
'缽' => '鉢',
'針' => '鍼',
'鯰' => '鮎',
'麵' => '麪',
'顎' => '齶',
);

View File

@@ -0,0 +1,70 @@
<?php return array (
'一口吃個' => '一口喫個',
'一口吃成' => '一口喫成',
'一家三口' => '一家三口',
'一家五口' => '一家五口',
'一家六口' => '一家六口',
'一家四口' => '一家四口',
'凶事' => '凶事',
'凶信' => '凶信',
'凶兆' => '凶兆',
'凶吉' => '凶吉',
'凶地' => '凶地',
'凶多吉少' => '凶多吉少',
'凶宅' => '凶宅',
'凶年' => '凶年',
'凶德' => '凶德',
'凶怪' => '凶怪',
'凶日' => '凶日',
'凶服' => '凶服',
'凶歲' => '凶歲',
'凶死' => '凶死',
'凶氣' => '凶氣',
'凶煞' => '凶煞',
'凶燄' => '凶燄',
'凶神' => '凶神',
'凶禮' => '凶禮',
'凶耗' => '凶耗',
'凶肆' => '凶肆',
'凶荒' => '凶荒',
'凶訊' => '凶訊',
'凶豎' => '凶豎',
'凶身' => '凶身',
'凶逆' => '凶逆',
'凶門' => '凶門',
'口吃' => '口吃',
'吃口' => '喫口',
'吃口令' => '吃口令',
'吃口飯' => '喫口飯',
'吃吃' => '喫喫',
'吃子' => '喫子',
'合著' => '合著',
'吉凶' => '吉凶',
'名著' => '名著',
'四凶' => '四凶',
'大凶' => '大凶',
'巨著' => '巨著',
'張口' => '張口',
'昭著' => '昭著',
'歲凶' => '歲凶',
'胃口' => '胃口',
'著作' => '著作',
'著名' => '著名',
'著式' => '著式',
'著志' => '著志',
'著於' => '著於',
'著書' => '著書',
'著白' => '著白',
'著稱' => '著稱',
'著者' => '著者',
'著述' => '著述',
'著錄' => '著錄',
'蹇吃' => '蹇吃',
'逢凶' => '逢凶',
'避凶' => '避凶',
'鄧艾吃' => '鄧艾吃',
'鉅著' => '鉅著',
'開口' => '開口',
'閔凶' => '閔凶',
'顯著' => '顯著',
);

View File

@@ -0,0 +1,180 @@
<?php
namespace Overtrue\PHPOpenCC\Console;
use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Input\InputDefinition;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Input\InputOption;
use Symfony\Component\Console\Output\OutputInterface;
use Symfony\Component\Process\Process;
class BuildCommand extends Command
{
protected static $defaultName = 'build';
protected static $defaultDescription = 'Build OpenCC data files.';
const DICTIONARY_DIR = __DIR__.'/../../data/dictionary';
const PARSED_DIR = __DIR__.'/../../data/parsed';
const FILES = [
'HKVariants',
'HKVariantsRevPhrases',
'JPShinjitaiCharacters',
'JPShinjitaiPhrases',
'JPVariants',
'STCharacters',
'STPhrases',
'TSCharacters',
'TSPhrases',
'TWPhrasesIT',
'TWPhrasesName',
'TWPhrasesOther',
'TWVariants',
'TWVariantsRevPhrases',
];
const MERGE_OUTPUT_MAP = [
'TWPhrases' => ['TWPhrasesIT', 'TWPhrasesName', 'TWPhrasesOther'],
'TWVariantsRev' => ['TWVariants'],
'TWPhrasesRev' => ['TWPhrasesIT', 'TWPhrasesName', 'TWPhrasesOther'],
'HKVariantsRev' => ['HKVariants'],
'JPVariantsRev' => ['JPVariants'],
];
const REVERSED_FILES = [
'TWVariantsRev',
'TWPhrasesRev',
'HKVariantsRev',
'JPVariantsRev',
];
protected function configure(): void
{
$this
->setDefinition(
new InputDefinition([
new InputOption('force', 'f', InputOption::VALUE_OPTIONAL),
])
);
}
/**
* @throws \Exception
*/
protected function execute(InputInterface $input, OutputInterface $output): int
{
if (! file_exists(self::DICTIONARY_DIR)) {
mkdir(self::DICTIONARY_DIR, 0755, true);
}
if (! file_exists(self::PARSED_DIR)) {
mkdir(self::PARSED_DIR, 0755, true);
}
$file = self::DICTIONARY_DIR.'/STCharacters.txt';
if (file_exists($file) && filemtime($file) > time() - 3600 * 24 && ! $input->hasOption('force')) {
$output->writeln('Data files are up to date.');
return Command::SUCCESS;
}
$this->download($output);
$this->extract($output);
$this->copy($output);
$this->parse($output);
return Command::SUCCESS;
}
/**
* @throws \Exception
*/
public function download(OutputInterface $output): void
{
$output->writeln('Downloading data files...');
$zip = 'https://github.com/BYVoid/OpenCC/archive/refs/heads/master.zip';
try {
$process = Process::fromShellCommandline('curl -L -o /tmp/opencc.zip '.$zip);
$process->setTty(Process::isTtySupported());
$process->run();
} catch (\Exception $e) {
$output->writeln('Download failed.');
throw $e;
}
$output->writeln('Done.');
}
public function copy(OutputInterface $output): void
{
$output->write('Copying data files...');
$process = Process::fromShellCommandline('cp -rf /tmp/opencc/OpenCC-master/data/dictionary/* '.self::DICTIONARY_DIR);
$process->setTty(Process::isTtySupported());
$process->run();
$output->writeln('Done.');
}
public function extract(OutputInterface $output): void
{
$output->write('Extracting data files...');
$process = Process::fromShellCommandline('unzip -o /tmp/opencc.zip -d /tmp/opencc');
$process->run();
$output->writeln('Done.');
}
public function parse(OutputInterface $output): void
{
$output->writeln('Parsing dictionary files...');
$files = array_merge(self::FILES, array_keys(self::MERGE_OUTPUT_MAP));
foreach ($files as $file) {
$output->writeln('Parsing '.$file.'...');
$txt = sprintf('%s/%s.txt', self::DICTIONARY_DIR, $file);
if (file_exists($txt)) {
$lines = file($txt, FILE_IGNORE_NEW_LINES | FILE_SKIP_EMPTY_LINES);
} else {
// merge files
$content = '';
foreach (self::MERGE_OUTPUT_MAP[$file] as $f) {
$content .= file_get_contents(sprintf('%s/%s.txt', self::DICTIONARY_DIR, $f));
}
$lines = array_filter(explode("\n", $content));
}
$needReverse = in_array($file, self::REVERSED_FILES, true);
$words = [];
foreach ($lines as $line) {
[$from, $to] = explode("\t", $line);
$to = preg_split('/\s+/', $to, -1, PREG_SPLIT_NO_EMPTY)[0] ?? null;
if (! $to) {
! $to && $output->writeln('Skip '.$line);
continue;
}
if ($needReverse) {
[$from, $to] = [$to, $from];
}
// 会出现重复的词条,以最后一个为准
$words[$from] = $to;
}
$content = sprintf('<?php return %s;', var_export($words, true));
$target = sprintf('%s/%s.php', self::PARSED_DIR, $file);
file_put_contents($target, $content);
}
$output->writeln('Done.');
}
}

View File

@@ -0,0 +1,36 @@
<?php
namespace Overtrue\PHPOpenCC\Console;
use Overtrue\PHPOpenCC\OpenCC;
use Overtrue\PHPOpenCC\Strategy;
use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Input\InputArgument;
use Symfony\Component\Console\Input\InputDefinition;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;
class ConvertCommand extends Command
{
protected static $defaultName = 'convert';
protected static $defaultDescription = '中文简繁转换,支持词汇级别的转换、异体字转换和地区习惯用词转换(中国大陆、台湾、香港、日本新字体)。';
protected function configure(): void
{
$this
->setDefinition(
new InputDefinition([
new InputArgument('string', InputArgument::REQUIRED, '待转换的字符串'),
new InputArgument('strategy', InputArgument::OPTIONAL, '转换策略', Strategy::SIMPLIFIED_TO_TRADITIONAL),
])
);
}
protected function execute(InputInterface $input, OutputInterface $output): int
{
$output->writeln(OpenCC::convert($input->getArgument('string'), $input->getArgument('strategy')));
return Command::SUCCESS;
}
}

View File

@@ -0,0 +1,25 @@
<?php
namespace Overtrue\PHPOpenCC\Contracts;
interface ConverterInterface
{
/**
* @param array<array<string, string>> $dictionaries
*
*@example
* $string = '一口吃個胖子';
* $dictionaries = [
* ['HKVariants' => ['一' => '壹', '個' => '個', '胖' => '胖', '子' => '子']],
* ['STPhrases' => ['壹個' => '一個']],
* // 可能同时包含多组词典
* [
* [
* 'HKVariantsRevPhrases' => ['一個' => '壹個'],
* 'HKVariantsRev' => ['壹' => '一', '個' => '個', '胖' => '胖', '子' => '子'],
* ]
* ]
* ]
*/
public function convert(string $string, array $dictionaries): string;
}

View File

@@ -0,0 +1,30 @@
<?php
namespace Overtrue\PHPOpenCC;
use Overtrue\PHPOpenCC\Contracts\ConverterInterface;
class Converter implements ConverterInterface
{
public function convert(string $string, array $dictionaries): string
{
foreach ($dictionaries as $dictionary) {
// [['f1' => 't1'], ['f2' => 't2'], ...]
if (is_array(reset($dictionary))) {
$tmp = [];
foreach ($dictionary as $dict) {
$tmp = array_merge($tmp, $dict);
}
$dictionary = $tmp;
}
uksort($dictionary, function ($a, $b) {
return mb_strlen($b) <=> mb_strlen($a);
});
$string = strtr($string, $dictionary);
}
return $string;
}
}

View File

@@ -0,0 +1,66 @@
<?php
namespace Overtrue\PHPOpenCC;
class Dictionary
{
const SETS_MAP = [
Strategy::SIMPLIFIED_TO_TRADITIONAL => [['STPhrases', 'STCharacters']], // S2T
Strategy::SIMPLIFIED_TO_HONGKONG => [['STPhrases', 'STCharacters'], 'HKVariants'], // S2HK
Strategy::SIMPLIFIED_TO_JAPANESE => [['STPhrases', 'STCharacters'], 'JPVariants'], // S2JP
Strategy::SIMPLIFIED_TO_TAIWAN => [['STPhrases', 'STCharacters'], 'TWVariants'], // S2TW
Strategy::SIMPLIFIED_TO_TAIWAN_WITH_PHRASE => [['STPhrases', 'STCharacters'], ['TWPhrases', 'TWVariants']], // S2TWP
Strategy::HONGKONG_TO_TRADITIONAL => [['HKVariantsRevPhrases', 'HKVariantsRev']], // HK2T
Strategy::HONGKONG_TO_SIMPLIFIED => [['HKVariantsRevPhrases', 'HKVariantsRev'], ['TSPhrases', 'TSCharacters']], // HK2S
Strategy::TAIWAN_TO_SIMPLIFIED => [['TWVariantsRevPhrases', 'TWVariantsRev'], ['TSPhrases', 'TSCharacters']], // TW2S
Strategy::TAIWAN_TO_TRADITIONAL => [['TWVariantsRevPhrases', 'TWVariantsRev']], // TW2T
Strategy::TAIWAN_TO_SIMPLIFIED_WITH_PHRASE => [['TWPhrasesRev', 'TWVariantsRevPhrases', 'TWVariantsRev'], ['TSPhrases', 'TSCharacters']], // TW2SP
Strategy::TRADITIONAL_TO_HONGKONG => ['HKVariants'], // T2HK
Strategy::TRADITIONAL_TO_SIMPLIFIED => [['TSPhrases', 'TSCharacters']], // T2S
Strategy::TRADITIONAL_TO_TAIWAN => ['TWVariants'], // T2TW
Strategy::TRADITIONAL_TO_JAPANESE => ['JPVariants'], // T2JP
Strategy::JAPANESE_TO_TRADITIONAL => [['JPShinjitaiPhrases', 'JPShinjitaiCharacters', 'JPVariantsRev']], // JP2T
Strategy::JAPANESE_TO_SIMPLIFIED => [['JPShinjitaiPhrases', 'JPShinjitaiCharacters', 'JPVariantsRev'], ['TSPhrases', 'TSCharacters']], // JP2S
];
const PARSED_DIR = __DIR__.'/../data/parsed';
/**
* @return array<string, array<string, string>>
*/
public static function get(string $set): array
{
$set = constant(Strategy::class.'::'.strtoupper($set));
if (! array_key_exists($set, self::SETS_MAP)) {
throw new \InvalidArgumentException("Dictionary set [{$set}] does not exists.");
}
$dictionaries = [];
foreach (self::SETS_MAP[$set] as $dictionary) {
if (is_array($dictionary)) {
$group = [];
foreach ($dictionary as $dict) {
$group[$dict] = self::loadDictionary($dict);
}
$dictionaries[] = $group;
continue;
}
$dictionaries[$dictionary] = self::loadDictionary($dictionary);
}
return $dictionaries;
}
protected static function loadDictionary(string $dictionary)
{
$dictionary = sprintf('%s/%s.php', self::PARSED_DIR, $dictionary);
if (! file_exists($dictionary)) {
throw new \InvalidArgumentException("Dictionary [{$dictionary}] does not exists.");
}
return require $dictionary;
}
}

View File

@@ -0,0 +1,61 @@
<?php
namespace Overtrue\PHPOpenCC;
/**
* @method static string s2t(string $input)
* @method static string s2hk(string $input)
* @method static string s2jp(string $input)
* @method static string s2tw(string $input)
* @method static string s2twp(string $input)
* @method static string hk2t(string $input)
* @method static string hk2s(string $input)
* @method static string tw2s(string $input)
* @method static string tw2t(string $input)
* @method static string tw2sp(string $input)
* @method static string t2hk(string $input)
* @method static string t2s(string $input)
* @method static string t2tw(string $input)
* @method static string t2jp(string $input)
* @method static string jp2t(string $input)
* @method static string jp2s(string $input)
* @method static string simplifiedToTraditional(string $input)
* @method static string simplifiedToHongkong(string $input)
* @method static string simplifiedToJapanese(string $input)
* @method static string simplifiedToTaiwan(string $input)
* @method static string simplifiedToTaiwan_with_phrase(string $input)
* @method static string hongkongToTraditional(string $input)
* @method static string hongkongToSimplified(string $input)
* @method static string taiwanToSimplified(string $input)
* @method static string taiwanToTraditional(string $input)
* @method static string taiwanToSimplified_with_phrase(string $input)
* @method static string traditionalToHongkong(string $input)
* @method static string traditionalToSimplified(string $input)
* @method static string traditionalToTaiwan(string $input)
* @method static string traditionalToJapanese(string $input)
* @method static string japaneseToTraditional(string $input)
* @method static string japaneseToSimplified(string $input)
*/
class OpenCC
{
public static function convert(string $input, string $strategy = Strategy::SIMPLIFIED_TO_TRADITIONAL): string
{
$converter = new Converter();
return $converter->convert($input, Dictionary::get($strategy));
}
public static function __callStatic(string $name, array $arguments)
{
// s2t() => Strategy::S2T => (), simplifiedToTraditional() -> Strategy::SIMPLIFIED_TO_TRADITIONAL
$strategy = strtoupper(preg_replace_callback('/[A-Z]/', function ($matches) {
return '_'.$matches[0];
}, lcfirst($name)));
if (! constant(Strategy::class.'::'.strtoupper($strategy))) {
throw new \BadMethodCallException(sprintf('Method "%s" does not exist.', $strategy));
}
return static::convert($arguments[0], constant(Strategy::class.'::'.$strategy));
}
}

View File

@@ -0,0 +1,71 @@
<?php
namespace Overtrue\PHPOpenCC;
class Strategy
{
// aliases
const S2T = 'SIMPLIFIED_TO_TRADITIONAL';
const S2HK = 'SIMPLIFIED_TO_HONGKONG';
const S2JP = 'SIMPLIFIED_TO_JAPANESE';
const S2TW = 'SIMPLIFIED_TO_TAIWAN';
const S2TWP = 'SIMPLIFIED_TO_TAIWAN_WITH_PHRASE';
const HK2T = 'HONGKONG_TO_TRADITIONAL';
const HK2S = 'HONGKONG_TO_SIMPLIFIED';
const TW2S = 'TAIWAN_TO_SIMPLIFIED';
const TW2T = 'TAIWAN_TO_TRADITIONAL';
const TW2SP = 'TAIWAN_TO_SIMPLIFIED_WITH_PHRASE';
const T2HK = 'TRADITIONAL_TO_HONGKONG';
const T2S = 'TRADITIONAL_TO_SIMPLIFIED';
const T2TW = 'TRADITIONAL_TO_TAIWAN';
const T2JP = 'TRADITIONAL_TO_JAPANESE';
const JP2T = 'JAPANESE_TO_TRADITIONAL';
const JP2S = 'JAPANESE_TO_SIMPLIFIED';
const SIMPLIFIED_TO_TRADITIONAL = 'SIMPLIFIED_TO_TRADITIONAL';
const SIMPLIFIED_TO_HONGKONG = 'SIMPLIFIED_TO_HONGKONG';
const SIMPLIFIED_TO_JAPANESE = 'SIMPLIFIED_TO_JAPANESE';
const SIMPLIFIED_TO_TAIWAN = 'SIMPLIFIED_TO_TAIWAN';
const SIMPLIFIED_TO_TAIWAN_WITH_PHRASE = 'SIMPLIFIED_TO_TAIWAN_WITH_PHRASE';
const HONGKONG_TO_TRADITIONAL = 'HONGKONG_TO_TRADITIONAL';
const HONGKONG_TO_SIMPLIFIED = 'HONGKONG_TO_SIMPLIFIED';
const TAIWAN_TO_SIMPLIFIED = 'TAIWAN_TO_SIMPLIFIED';
const TAIWAN_TO_TRADITIONAL = 'TAIWAN_TO_TRADITIONAL';
const TAIWAN_TO_SIMPLIFIED_WITH_PHRASE = 'TAIWAN_TO_SIMPLIFIED_WITH_PHRASE';
const TRADITIONAL_TO_HONGKONG = 'TRADITIONAL_TO_HONGKONG';
const TRADITIONAL_TO_SIMPLIFIED = 'TRADITIONAL_TO_SIMPLIFIED';
const TRADITIONAL_TO_TAIWAN = 'TRADITIONAL_TO_TAIWAN';
const TRADITIONAL_TO_JAPANESE = 'TRADITIONAL_TO_JAPANESE';
const JAPANESE_TO_TRADITIONAL = 'JAPANESE_TO_TRADITIONAL';
const JAPANESE_TO_SIMPLIFIED = 'JAPANESE_TO_SIMPLIFIED';
}

View File

@@ -0,0 +1,3 @@
composer.lock
composer.phar
/vendor/

View File

@@ -0,0 +1,21 @@
The MIT License (MIT)
Copyright (c) 2013-2016 container-interop
Copyright (c) 2016 PHP Framework Interoperability Group
Permission is hereby granted, free of charge, to any person obtaining a copy of
this software and associated documentation files (the "Software"), to deal in
the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
the Software, and to permit persons to whom the Software is furnished to do so,
subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

View File

@@ -0,0 +1,13 @@
Container interface
==============
This repository holds all interfaces related to [PSR-11 (Container Interface)][psr-url].
Note that this is not a Container implementation of its own. It is merely abstractions that describe the components of a Dependency Injection Container.
The installable [package][package-url] and [implementations][implementation-url] are listed on Packagist.
[psr-url]: https://www.php-fig.org/psr/psr-11/
[package-url]: https://packagist.org/packages/psr/container
[implementation-url]: https://packagist.org/providers/psr/container-implementation

View File

@@ -0,0 +1,27 @@
{
"name": "psr/container",
"type": "library",
"description": "Common Container Interface (PHP FIG PSR-11)",
"keywords": ["psr", "psr-11", "container", "container-interop", "container-interface"],
"homepage": "https://github.com/php-fig/container",
"license": "MIT",
"authors": [
{
"name": "PHP-FIG",
"homepage": "https://www.php-fig.org/"
}
],
"require": {
"php": ">=7.4.0"
},
"autoload": {
"psr-4": {
"Psr\\Container\\": "src/"
}
},
"extra": {
"branch-alias": {
"dev-master": "2.0.x-dev"
}
}
}

View File

@@ -0,0 +1,12 @@
<?php
namespace Psr\Container;
use Throwable;
/**
* Base interface representing a generic exception in a container.
*/
interface ContainerExceptionInterface extends Throwable
{
}

View File

@@ -0,0 +1,36 @@
<?php
declare(strict_types=1);
namespace Psr\Container;
/**
* Describes the interface of a container that exposes methods to read its entries.
*/
interface ContainerInterface
{
/**
* Finds an entry of the container by its identifier and returns it.
*
* @param string $id Identifier of the entry to look for.
*
* @throws NotFoundExceptionInterface No entry was found for **this** identifier.
* @throws ContainerExceptionInterface Error while retrieving the entry.
*
* @return mixed Entry.
*/
public function get(string $id);
/**
* Returns true if the container can return an entry for the given identifier.
* Returns false otherwise.
*
* `has($id)` returning true does not mean that `get($id)` will not throw an exception.
* It does however mean that `get($id)` will not throw a `NotFoundExceptionInterface`.
*
* @param string $id Identifier of the entry to look for.
*
* @return bool
*/
public function has(string $id): bool;
}

View File

@@ -0,0 +1,10 @@
<?php
namespace Psr\Container;
/**
* No entry was found in the container.
*/
interface NotFoundExceptionInterface extends ContainerExceptionInterface
{
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,39 @@
<?php
/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Symfony\Component\Console\Attribute;
/**
* Service tag to autoconfigure commands.
*/
#[\Attribute(\Attribute::TARGET_CLASS)]
class AsCommand
{
public function __construct(
public string $name,
public ?string $description = null,
array $aliases = [],
bool $hidden = false,
) {
if (!$hidden && !$aliases) {
return;
}
$name = explode('|', $name);
$name = array_merge($name, $aliases);
if ($hidden && '' !== $name[0]) {
array_unshift($name, '');
}
$this->name = implode('|', $name);
}
}

View File

@@ -0,0 +1,261 @@
CHANGELOG
=========
6.4
---
* Add `SignalMap` to map signal value to its name
* Multi-line text in vertical tables is aligned properly
* The application can also catch errors with `Application::setCatchErrors(true)`
* Add `RunCommandMessage` and `RunCommandMessageHandler`
* Dispatch `ConsoleTerminateEvent` after an exit on signal handling and add `ConsoleTerminateEvent::getInterruptingSignal()`
6.3
---
* Add support for choosing exit code while handling signal, or to not exit at all
* Add `ProgressBar::setPlaceholderFormatter` to set a placeholder attached to a instance, instead of being global.
* Add `ReStructuredTextDescriptor`
6.2
---
* Improve truecolor terminal detection in some cases
* Add support for 256 color terminals (conversion from Ansi24 to Ansi8 if terminal is capable of it)
* Deprecate calling `*Command::setApplication()`, `*FormatterStyle::setForeground/setBackground()`, `Helper::setHelpSet()`, `Input*::setDefault()`, `Question::setAutocompleterCallback/setValidator()`without any arguments
* Change the signature of `OutputFormatterStyleInterface::setForeground/setBackground()` to `setForeground/setBackground(?string)`
* Change the signature of `HelperInterface::setHelperSet()` to `setHelperSet(?HelperSet)`
6.1
---
* Add support to display table vertically when calling setVertical()
* Add method `__toString()` to `InputInterface`
* Added `OutputWrapper` to prevent truncated URL in `SymfonyStyle::createBlock`.
* Deprecate `Command::$defaultName` and `Command::$defaultDescription`, use the `AsCommand` attribute instead
* Add suggested values for arguments and options in input definition, for input completion
* Add `$resumeAt` parameter to `ProgressBar#start()`, so that one can easily 'resume' progress on longer tasks, and still get accurate `getEstimate()` and `getRemaining()` results.
6.0
---
* `Command::setHidden()` has a default value (`true`) for `$hidden` parameter and is final
* Remove `Helper::strlen()`, use `Helper::width()` instead
* Remove `Helper::strlenWithoutDecoration()`, use `Helper::removeDecoration()` instead
* `AddConsoleCommandPass` can not be configured anymore
* Remove `HelperSet::setCommand()` and `getCommand()` without replacement
5.4
---
* Add `TesterTrait::assertCommandIsSuccessful()` to test command
* Deprecate `HelperSet::setCommand()` and `getCommand()` without replacement
5.3
---
* Add `GithubActionReporter` to render annotations in a Github Action
* Add `InputOption::VALUE_NEGATABLE` flag to handle `--foo`/`--no-foo` options
* Add the `Command::$defaultDescription` static property and the `description` attribute
on the `console.command` tag to allow the `list` command to instantiate commands lazily
* Add option `--short` to the `list` command
* Add support for bright colors
* Add `#[AsCommand]` attribute for declaring commands on PHP 8
* Add `Helper::width()` and `Helper::length()`
* The `--ansi` and `--no-ansi` options now default to `null`.
5.2.0
-----
* Added `SingleCommandApplication::setAutoExit()` to allow testing via `CommandTester`
* added support for multiline responses to questions through `Question::setMultiline()`
and `Question::isMultiline()`
* Added `SignalRegistry` class to stack signals handlers
* Added support for signals:
* Added `Application::getSignalRegistry()` and `Application::setSignalsToDispatchEvent()` methods
* Added `SignalableCommandInterface` interface
* Added `TableCellStyle` class to customize table cell
* Removed `php ` prefix invocation from help messages.
5.1.0
-----
* `Command::setHidden()` is final since Symfony 5.1
* Add `SingleCommandApplication`
* Add `Cursor` class
5.0.0
-----
* removed support for finding hidden commands using an abbreviation, use the full name instead
* removed `TableStyle::setCrossingChar()` method in favor of `TableStyle::setDefaultCrossingChar()`
* removed `TableStyle::setHorizontalBorderChar()` method in favor of `TableStyle::setDefaultCrossingChars()`
* removed `TableStyle::getHorizontalBorderChar()` method in favor of `TableStyle::getBorderChars()`
* removed `TableStyle::setVerticalBorderChar()` method in favor of `TableStyle::setVerticalBorderChars()`
* removed `TableStyle::getVerticalBorderChar()` method in favor of `TableStyle::getBorderChars()`
* removed support for returning `null` from `Command::execute()`, return `0` instead
* `ProcessHelper::run()` accepts only `array|Symfony\Component\Process\Process` for its `command` argument
* `Application::setDispatcher` accepts only `Symfony\Contracts\EventDispatcher\EventDispatcherInterface`
for its `dispatcher` argument
* renamed `Application::renderException()` and `Application::doRenderException()`
to `renderThrowable()` and `doRenderThrowable()` respectively.
4.4.0
-----
* deprecated finding hidden commands using an abbreviation, use the full name instead
* added `Question::setTrimmable` default to true to allow the answer to be trimmed
* added method `minSecondsBetweenRedraws()` and `maxSecondsBetweenRedraws()` on `ProgressBar`
* `Application` implements `ResetInterface`
* marked all dispatched event classes as `@final`
* added support for displaying table horizontally
* deprecated returning `null` from `Command::execute()`, return `0` instead
* Deprecated the `Application::renderException()` and `Application::doRenderException()` methods,
use `renderThrowable()` and `doRenderThrowable()` instead.
* added support for the `NO_COLOR` env var (https://no-color.org/)
4.3.0
-----
* added support for hyperlinks
* added `ProgressBar::iterate()` method that simplify updating the progress bar when iterating
* added `Question::setAutocompleterCallback()` to provide a callback function
that dynamically generates suggestions as the user types
4.2.0
-----
* allowed passing commands as `[$process, 'ENV_VAR' => 'value']` to
`ProcessHelper::run()` to pass environment variables
* deprecated passing a command as a string to `ProcessHelper::run()`,
pass it the command as an array of its arguments instead
* made the `ProcessHelper` class final
* added `WrappableOutputFormatterInterface::formatAndWrap()` (implemented in `OutputFormatter`)
* added `capture_stderr_separately` option to `CommandTester::execute()`
4.1.0
-----
* added option to run suggested command if command is not found and only 1 alternative is available
* added option to modify console output and print multiple modifiable sections
* added support for iterable messages in output `write` and `writeln` methods
4.0.0
-----
* `OutputFormatter` throws an exception when unknown options are used
* removed `QuestionHelper::setInputStream()/getInputStream()`
* removed `Application::getTerminalWidth()/getTerminalHeight()` and
`Application::setTerminalDimensions()/getTerminalDimensions()`
* removed `ConsoleExceptionEvent`
* removed `ConsoleEvents::EXCEPTION`
3.4.0
-----
* added `SHELL_VERBOSITY` env var to control verbosity
* added `CommandLoaderInterface`, `FactoryCommandLoader` and PSR-11
`ContainerCommandLoader` for commands lazy-loading
* added a case-insensitive command name matching fallback
* added static `Command::$defaultName/getDefaultName()`, allowing for
commands to be registered at compile time in the application command loader.
Setting the `$defaultName` property avoids the need for filling the `command`
attribute on the `console.command` tag when using `AddConsoleCommandPass`.
3.3.0
-----
* added `ExceptionListener`
* added `AddConsoleCommandPass` (originally in FrameworkBundle)
* [BC BREAK] `Input::getOption()` no longer returns the default value for options
with value optional explicitly passed empty
* added console.error event to catch exceptions thrown by other listeners
* deprecated console.exception event in favor of console.error
* added ability to handle `CommandNotFoundException` through the
`console.error` event
* deprecated default validation in `SymfonyQuestionHelper::ask`
3.2.0
------
* added `setInputs()` method to CommandTester for ease testing of commands expecting inputs
* added `setStream()` and `getStream()` methods to Input (implement StreamableInputInterface)
* added StreamableInputInterface
* added LockableTrait
3.1.0
-----
* added truncate method to FormatterHelper
* added setColumnWidth(s) method to Table
2.8.3
-----
* remove readline support from the question helper as it caused issues
2.8.0
-----
* use readline for user input in the question helper when available to allow
the use of arrow keys
2.6.0
-----
* added a Process helper
* added a DebugFormatter helper
2.5.0
-----
* deprecated the dialog helper (use the question helper instead)
* deprecated TableHelper in favor of Table
* deprecated ProgressHelper in favor of ProgressBar
* added ConsoleLogger
* added a question helper
* added a way to set the process name of a command
* added a way to set a default command instead of `ListCommand`
2.4.0
-----
* added a way to force terminal dimensions
* added a convenient method to detect verbosity level
* [BC BREAK] made descriptors use output instead of returning a string
2.3.0
-----
* added multiselect support to the select dialog helper
* added Table Helper for tabular data rendering
* added support for events in `Application`
* added a way to normalize EOLs in `ApplicationTester::getDisplay()` and `CommandTester::getDisplay()`
* added a way to set the progress bar progress via the `setCurrent` method
* added support for multiple InputOption shortcuts, written as `'-a|-b|-c'`
* added two additional verbosity levels, VERBOSITY_VERY_VERBOSE and VERBOSITY_DEBUG
2.2.0
-----
* added support for colorization on Windows via ConEmu
* add a method to Dialog Helper to ask for a question and hide the response
* added support for interactive selections in console (DialogHelper::select())
* added support for autocompletion as you type in Dialog Helper
2.1.0
-----
* added ConsoleOutputInterface
* added the possibility to disable a command (Command::isEnabled())
* added suggestions when a command does not exist
* added a --raw option to the list command
* added support for STDERR in the console output class (errors are now sent
to STDERR)
* made the defaults (helper set, commands, input definition) in Application
more easily customizable
* added support for the shell even if readline is not available
* added support for process isolation in Symfony shell via
`--process-isolation` switch
* added support for `--`, which disables options parsing after that point
(tokens will be parsed as arguments)

View File

@@ -0,0 +1,99 @@
<?php
/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Symfony\Component\Console\CI;
use Symfony\Component\Console\Output\OutputInterface;
/**
* Utility class for Github actions.
*
* @author Maxime Steinhausser <maxime.steinhausser@gmail.com>
*/
class GithubActionReporter
{
private OutputInterface $output;
/**
* @see https://github.com/actions/toolkit/blob/5e5e1b7aacba68a53836a34db4a288c3c1c1585b/packages/core/src/command.ts#L80-L85
*/
private const ESCAPED_DATA = [
'%' => '%25',
"\r" => '%0D',
"\n" => '%0A',
];
/**
* @see https://github.com/actions/toolkit/blob/5e5e1b7aacba68a53836a34db4a288c3c1c1585b/packages/core/src/command.ts#L87-L94
*/
private const ESCAPED_PROPERTIES = [
'%' => '%25',
"\r" => '%0D',
"\n" => '%0A',
':' => '%3A',
',' => '%2C',
];
public function __construct(OutputInterface $output)
{
$this->output = $output;
}
public static function isGithubActionEnvironment(): bool
{
return false !== getenv('GITHUB_ACTIONS');
}
/**
* Output an error using the Github annotations format.
*
* @see https://docs.github.com/en/free-pro-team@latest/actions/reference/workflow-commands-for-github-actions#setting-an-error-message
*/
public function error(string $message, ?string $file = null, ?int $line = null, ?int $col = null): void
{
$this->log('error', $message, $file, $line, $col);
}
/**
* Output a warning using the Github annotations format.
*
* @see https://docs.github.com/en/free-pro-team@latest/actions/reference/workflow-commands-for-github-actions#setting-a-warning-message
*/
public function warning(string $message, ?string $file = null, ?int $line = null, ?int $col = null): void
{
$this->log('warning', $message, $file, $line, $col);
}
/**
* Output a debug log using the Github annotations format.
*
* @see https://docs.github.com/en/free-pro-team@latest/actions/reference/workflow-commands-for-github-actions#setting-a-debug-message
*/
public function debug(string $message, ?string $file = null, ?int $line = null, ?int $col = null): void
{
$this->log('debug', $message, $file, $line, $col);
}
private function log(string $type, string $message, ?string $file = null, ?int $line = null, ?int $col = null): void
{
// Some values must be encoded.
$message = strtr($message, self::ESCAPED_DATA);
if (!$file) {
// No file provided, output the message solely:
$this->output->writeln(sprintf('::%s::%s', $type, $message));
return;
}
$this->output->writeln(sprintf('::%s file=%s,line=%s,col=%s::%s', $type, strtr($file, self::ESCAPED_PROPERTIES), strtr($line ?? 1, self::ESCAPED_PROPERTIES), strtr($col ?? 0, self::ESCAPED_PROPERTIES), $message));
}
}

View File

@@ -0,0 +1,133 @@
<?php
/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Symfony\Component\Console;
use Symfony\Component\Console\Exception\InvalidArgumentException;
/**
* @author Fabien Potencier <fabien@symfony.com>
*/
final class Color
{
private const COLORS = [
'black' => 0,
'red' => 1,
'green' => 2,
'yellow' => 3,
'blue' => 4,
'magenta' => 5,
'cyan' => 6,
'white' => 7,
'default' => 9,
];
private const BRIGHT_COLORS = [
'gray' => 0,
'bright-red' => 1,
'bright-green' => 2,
'bright-yellow' => 3,
'bright-blue' => 4,
'bright-magenta' => 5,
'bright-cyan' => 6,
'bright-white' => 7,
];
private const AVAILABLE_OPTIONS = [
'bold' => ['set' => 1, 'unset' => 22],
'underscore' => ['set' => 4, 'unset' => 24],
'blink' => ['set' => 5, 'unset' => 25],
'reverse' => ['set' => 7, 'unset' => 27],
'conceal' => ['set' => 8, 'unset' => 28],
];
private string $foreground;
private string $background;
private array $options = [];
public function __construct(string $foreground = '', string $background = '', array $options = [])
{
$this->foreground = $this->parseColor($foreground);
$this->background = $this->parseColor($background, true);
foreach ($options as $option) {
if (!isset(self::AVAILABLE_OPTIONS[$option])) {
throw new InvalidArgumentException(sprintf('Invalid option specified: "%s". Expected one of (%s).', $option, implode(', ', array_keys(self::AVAILABLE_OPTIONS))));
}
$this->options[$option] = self::AVAILABLE_OPTIONS[$option];
}
}
public function apply(string $text): string
{
return $this->set().$text.$this->unset();
}
public function set(): string
{
$setCodes = [];
if ('' !== $this->foreground) {
$setCodes[] = $this->foreground;
}
if ('' !== $this->background) {
$setCodes[] = $this->background;
}
foreach ($this->options as $option) {
$setCodes[] = $option['set'];
}
if (0 === \count($setCodes)) {
return '';
}
return sprintf("\033[%sm", implode(';', $setCodes));
}
public function unset(): string
{
$unsetCodes = [];
if ('' !== $this->foreground) {
$unsetCodes[] = 39;
}
if ('' !== $this->background) {
$unsetCodes[] = 49;
}
foreach ($this->options as $option) {
$unsetCodes[] = $option['unset'];
}
if (0 === \count($unsetCodes)) {
return '';
}
return sprintf("\033[%sm", implode(';', $unsetCodes));
}
private function parseColor(string $color, bool $background = false): string
{
if ('' === $color) {
return '';
}
if ('#' === $color[0]) {
return ($background ? '4' : '3').Terminal::getColorMode()->convertFromHexToAnsiColorCode($color);
}
if (isset(self::COLORS[$color])) {
return ($background ? '4' : '3').self::COLORS[$color];
}
if (isset(self::BRIGHT_COLORS[$color])) {
return ($background ? '10' : '9').self::BRIGHT_COLORS[$color];
}
throw new InvalidArgumentException(sprintf('Invalid "%s" color; expected one of (%s).', $color, implode(', ', array_merge(array_keys(self::COLORS), array_keys(self::BRIGHT_COLORS)))));
}
}

View File

@@ -0,0 +1,725 @@
<?php
/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Symfony\Component\Console\Command;
use Symfony\Component\Console\Application;
use Symfony\Component\Console\Attribute\AsCommand;
use Symfony\Component\Console\Completion\CompletionInput;
use Symfony\Component\Console\Completion\CompletionSuggestions;
use Symfony\Component\Console\Completion\Suggestion;
use Symfony\Component\Console\Exception\ExceptionInterface;
use Symfony\Component\Console\Exception\InvalidArgumentException;
use Symfony\Component\Console\Exception\LogicException;
use Symfony\Component\Console\Helper\HelperInterface;
use Symfony\Component\Console\Helper\HelperSet;
use Symfony\Component\Console\Input\InputArgument;
use Symfony\Component\Console\Input\InputDefinition;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Input\InputOption;
use Symfony\Component\Console\Output\OutputInterface;
/**
* Base class for all commands.
*
* @author Fabien Potencier <fabien@symfony.com>
*/
class Command
{
// see https://tldp.org/LDP/abs/html/exitcodes.html
public const SUCCESS = 0;
public const FAILURE = 1;
public const INVALID = 2;
/**
* @var string|null The default command name
*
* @deprecated since Symfony 6.1, use the AsCommand attribute instead
*/
protected static $defaultName;
/**
* @var string|null The default command description
*
* @deprecated since Symfony 6.1, use the AsCommand attribute instead
*/
protected static $defaultDescription;
private ?Application $application = null;
private ?string $name = null;
private ?string $processTitle = null;
private array $aliases = [];
private InputDefinition $definition;
private bool $hidden = false;
private string $help = '';
private string $description = '';
private ?InputDefinition $fullDefinition = null;
private bool $ignoreValidationErrors = false;
private ?\Closure $code = null;
private array $synopsis = [];
private array $usages = [];
private ?HelperSet $helperSet = null;
public static function getDefaultName(): ?string
{
$class = static::class;
if ($attribute = (new \ReflectionClass($class))->getAttributes(AsCommand::class)) {
return $attribute[0]->newInstance()->name;
}
$r = new \ReflectionProperty($class, 'defaultName');
if ($class !== $r->class || null === static::$defaultName) {
return null;
}
trigger_deprecation('symfony/console', '6.1', 'Relying on the static property "$defaultName" for setting a command name is deprecated. Add the "%s" attribute to the "%s" class instead.', AsCommand::class, static::class);
return static::$defaultName;
}
public static function getDefaultDescription(): ?string
{
$class = static::class;
if ($attribute = (new \ReflectionClass($class))->getAttributes(AsCommand::class)) {
return $attribute[0]->newInstance()->description;
}
$r = new \ReflectionProperty($class, 'defaultDescription');
if ($class !== $r->class || null === static::$defaultDescription) {
return null;
}
trigger_deprecation('symfony/console', '6.1', 'Relying on the static property "$defaultDescription" for setting a command description is deprecated. Add the "%s" attribute to the "%s" class instead.', AsCommand::class, static::class);
return static::$defaultDescription;
}
/**
* @param string|null $name The name of the command; passing null means it must be set in configure()
*
* @throws LogicException When the command name is empty
*/
public function __construct(?string $name = null)
{
$this->definition = new InputDefinition();
if (null === $name && null !== $name = static::getDefaultName()) {
$aliases = explode('|', $name);
if ('' === $name = array_shift($aliases)) {
$this->setHidden(true);
$name = array_shift($aliases);
}
$this->setAliases($aliases);
}
if (null !== $name) {
$this->setName($name);
}
if ('' === $this->description) {
$this->setDescription(static::getDefaultDescription() ?? '');
}
$this->configure();
}
/**
* Ignores validation errors.
*
* This is mainly useful for the help command.
*
* @return void
*/
public function ignoreValidationErrors()
{
$this->ignoreValidationErrors = true;
}
/**
* @return void
*/
public function setApplication(?Application $application = null)
{
if (1 > \func_num_args()) {
trigger_deprecation('symfony/console', '6.2', 'Calling "%s()" without any arguments is deprecated, pass null explicitly instead.', __METHOD__);
}
$this->application = $application;
if ($application) {
$this->setHelperSet($application->getHelperSet());
} else {
$this->helperSet = null;
}
$this->fullDefinition = null;
}
/**
* @return void
*/
public function setHelperSet(HelperSet $helperSet)
{
$this->helperSet = $helperSet;
}
/**
* Gets the helper set.
*/
public function getHelperSet(): ?HelperSet
{
return $this->helperSet;
}
/**
* Gets the application instance for this command.
*/
public function getApplication(): ?Application
{
return $this->application;
}
/**
* Checks whether the command is enabled or not in the current environment.
*
* Override this to check for x or y and return false if the command cannot
* run properly under the current conditions.
*
* @return bool
*/
public function isEnabled()
{
return true;
}
/**
* Configures the current command.
*
* @return void
*/
protected function configure()
{
}
/**
* Executes the current command.
*
* This method is not abstract because you can use this class
* as a concrete class. In this case, instead of defining the
* execute() method, you set the code to execute by passing
* a Closure to the setCode() method.
*
* @return int 0 if everything went fine, or an exit code
*
* @throws LogicException When this abstract method is not implemented
*
* @see setCode()
*/
protected function execute(InputInterface $input, OutputInterface $output)
{
throw new LogicException('You must override the execute() method in the concrete command class.');
}
/**
* Interacts with the user.
*
* This method is executed before the InputDefinition is validated.
* This means that this is the only place where the command can
* interactively ask for values of missing required arguments.
*
* @return void
*/
protected function interact(InputInterface $input, OutputInterface $output)
{
}
/**
* Initializes the command after the input has been bound and before the input
* is validated.
*
* This is mainly useful when a lot of commands extends one main command
* where some things need to be initialized based on the input arguments and options.
*
* @see InputInterface::bind()
* @see InputInterface::validate()
*
* @return void
*/
protected function initialize(InputInterface $input, OutputInterface $output)
{
}
/**
* Runs the command.
*
* The code to execute is either defined directly with the
* setCode() method or by overriding the execute() method
* in a sub-class.
*
* @return int The command exit code
*
* @throws ExceptionInterface When input binding fails. Bypass this by calling {@link ignoreValidationErrors()}.
*
* @see setCode()
* @see execute()
*/
public function run(InputInterface $input, OutputInterface $output): int
{
// add the application arguments and options
$this->mergeApplicationDefinition();
// bind the input against the command specific arguments/options
try {
$input->bind($this->getDefinition());
} catch (ExceptionInterface $e) {
if (!$this->ignoreValidationErrors) {
throw $e;
}
}
$this->initialize($input, $output);
if (null !== $this->processTitle) {
if (\function_exists('cli_set_process_title')) {
if (!@cli_set_process_title($this->processTitle)) {
if ('Darwin' === \PHP_OS) {
$output->writeln('<comment>Running "cli_set_process_title" as an unprivileged user is not supported on MacOS.</comment>', OutputInterface::VERBOSITY_VERY_VERBOSE);
} else {
cli_set_process_title($this->processTitle);
}
}
} elseif (\function_exists('setproctitle')) {
setproctitle($this->processTitle);
} elseif (OutputInterface::VERBOSITY_VERY_VERBOSE === $output->getVerbosity()) {
$output->writeln('<comment>Install the proctitle PECL to be able to change the process title.</comment>');
}
}
if ($input->isInteractive()) {
$this->interact($input, $output);
}
// The command name argument is often omitted when a command is executed directly with its run() method.
// It would fail the validation if we didn't make sure the command argument is present,
// since it's required by the application.
if ($input->hasArgument('command') && null === $input->getArgument('command')) {
$input->setArgument('command', $this->getName());
}
$input->validate();
if ($this->code) {
$statusCode = ($this->code)($input, $output);
} else {
$statusCode = $this->execute($input, $output);
if (!\is_int($statusCode)) {
throw new \TypeError(sprintf('Return value of "%s::execute()" must be of the type int, "%s" returned.', static::class, get_debug_type($statusCode)));
}
}
return is_numeric($statusCode) ? (int) $statusCode : 0;
}
/**
* Adds suggestions to $suggestions for the current completion input (e.g. option or argument).
*/
public function complete(CompletionInput $input, CompletionSuggestions $suggestions): void
{
$definition = $this->getDefinition();
if (CompletionInput::TYPE_OPTION_VALUE === $input->getCompletionType() && $definition->hasOption($input->getCompletionName())) {
$definition->getOption($input->getCompletionName())->complete($input, $suggestions);
} elseif (CompletionInput::TYPE_ARGUMENT_VALUE === $input->getCompletionType() && $definition->hasArgument($input->getCompletionName())) {
$definition->getArgument($input->getCompletionName())->complete($input, $suggestions);
}
}
/**
* Sets the code to execute when running this command.
*
* If this method is used, it overrides the code defined
* in the execute() method.
*
* @param callable $code A callable(InputInterface $input, OutputInterface $output)
*
* @return $this
*
* @throws InvalidArgumentException
*
* @see execute()
*/
public function setCode(callable $code): static
{
if ($code instanceof \Closure) {
$r = new \ReflectionFunction($code);
if (null === $r->getClosureThis()) {
set_error_handler(static function () {});
try {
if ($c = \Closure::bind($code, $this)) {
$code = $c;
}
} finally {
restore_error_handler();
}
}
} else {
$code = $code(...);
}
$this->code = $code;
return $this;
}
/**
* Merges the application definition with the command definition.
*
* This method is not part of public API and should not be used directly.
*
* @param bool $mergeArgs Whether to merge or not the Application definition arguments to Command definition arguments
*
* @internal
*/
public function mergeApplicationDefinition(bool $mergeArgs = true): void
{
if (null === $this->application) {
return;
}
$this->fullDefinition = new InputDefinition();
$this->fullDefinition->setOptions($this->definition->getOptions());
$this->fullDefinition->addOptions($this->application->getDefinition()->getOptions());
if ($mergeArgs) {
$this->fullDefinition->setArguments($this->application->getDefinition()->getArguments());
$this->fullDefinition->addArguments($this->definition->getArguments());
} else {
$this->fullDefinition->setArguments($this->definition->getArguments());
}
}
/**
* Sets an array of argument and option instances.
*
* @return $this
*/
public function setDefinition(array|InputDefinition $definition): static
{
if ($definition instanceof InputDefinition) {
$this->definition = $definition;
} else {
$this->definition->setDefinition($definition);
}
$this->fullDefinition = null;
return $this;
}
/**
* Gets the InputDefinition attached to this Command.
*/
public function getDefinition(): InputDefinition
{
return $this->fullDefinition ?? $this->getNativeDefinition();
}
/**
* Gets the InputDefinition to be used to create representations of this Command.
*
* Can be overridden to provide the original command representation when it would otherwise
* be changed by merging with the application InputDefinition.
*
* This method is not part of public API and should not be used directly.
*/
public function getNativeDefinition(): InputDefinition
{
return $this->definition ?? throw new LogicException(sprintf('Command class "%s" is not correctly initialized. You probably forgot to call the parent constructor.', static::class));
}
/**
* Adds an argument.
*
* @param $mode The argument mode: InputArgument::REQUIRED or InputArgument::OPTIONAL
* @param $default The default value (for InputArgument::OPTIONAL mode only)
* @param array|\Closure(CompletionInput,CompletionSuggestions):list<string|Suggestion> $suggestedValues The values used for input completion
*
* @return $this
*
* @throws InvalidArgumentException When argument mode is not valid
*/
public function addArgument(string $name, ?int $mode = null, string $description = '', mixed $default = null /* array|\Closure $suggestedValues = null */): static
{
$suggestedValues = 5 <= \func_num_args() ? func_get_arg(4) : [];
if (!\is_array($suggestedValues) && !$suggestedValues instanceof \Closure) {
throw new \TypeError(sprintf('Argument 5 passed to "%s()" must be array or \Closure, "%s" given.', __METHOD__, get_debug_type($suggestedValues)));
}
$this->definition->addArgument(new InputArgument($name, $mode, $description, $default, $suggestedValues));
$this->fullDefinition?->addArgument(new InputArgument($name, $mode, $description, $default, $suggestedValues));
return $this;
}
/**
* Adds an option.
*
* @param $shortcut The shortcuts, can be null, a string of shortcuts delimited by | or an array of shortcuts
* @param $mode The option mode: One of the InputOption::VALUE_* constants
* @param $default The default value (must be null for InputOption::VALUE_NONE)
* @param array|\Closure(CompletionInput,CompletionSuggestions):list<string|Suggestion> $suggestedValues The values used for input completion
*
* @return $this
*
* @throws InvalidArgumentException If option mode is invalid or incompatible
*/
public function addOption(string $name, string|array|null $shortcut = null, ?int $mode = null, string $description = '', mixed $default = null /* array|\Closure $suggestedValues = [] */): static
{
$suggestedValues = 6 <= \func_num_args() ? func_get_arg(5) : [];
if (!\is_array($suggestedValues) && !$suggestedValues instanceof \Closure) {
throw new \TypeError(sprintf('Argument 5 passed to "%s()" must be array or \Closure, "%s" given.', __METHOD__, get_debug_type($suggestedValues)));
}
$this->definition->addOption(new InputOption($name, $shortcut, $mode, $description, $default, $suggestedValues));
$this->fullDefinition?->addOption(new InputOption($name, $shortcut, $mode, $description, $default, $suggestedValues));
return $this;
}
/**
* Sets the name of the command.
*
* This method can set both the namespace and the name if
* you separate them by a colon (:)
*
* $command->setName('foo:bar');
*
* @return $this
*
* @throws InvalidArgumentException When the name is invalid
*/
public function setName(string $name): static
{
$this->validateName($name);
$this->name = $name;
return $this;
}
/**
* Sets the process title of the command.
*
* This feature should be used only when creating a long process command,
* like a daemon.
*
* @return $this
*/
public function setProcessTitle(string $title): static
{
$this->processTitle = $title;
return $this;
}
/**
* Returns the command name.
*/
public function getName(): ?string
{
return $this->name;
}
/**
* @param bool $hidden Whether or not the command should be hidden from the list of commands
*
* @return $this
*/
public function setHidden(bool $hidden = true): static
{
$this->hidden = $hidden;
return $this;
}
/**
* @return bool whether the command should be publicly shown or not
*/
public function isHidden(): bool
{
return $this->hidden;
}
/**
* Sets the description for the command.
*
* @return $this
*/
public function setDescription(string $description): static
{
$this->description = $description;
return $this;
}
/**
* Returns the description for the command.
*/
public function getDescription(): string
{
return $this->description;
}
/**
* Sets the help for the command.
*
* @return $this
*/
public function setHelp(string $help): static
{
$this->help = $help;
return $this;
}
/**
* Returns the help for the command.
*/
public function getHelp(): string
{
return $this->help;
}
/**
* Returns the processed help for the command replacing the %command.name% and
* %command.full_name% patterns with the real values dynamically.
*/
public function getProcessedHelp(): string
{
$name = $this->name;
$isSingleCommand = $this->application?->isSingleCommand();
$placeholders = [
'%command.name%',
'%command.full_name%',
];
$replacements = [
$name,
$isSingleCommand ? $_SERVER['PHP_SELF'] : $_SERVER['PHP_SELF'].' '.$name,
];
return str_replace($placeholders, $replacements, $this->getHelp() ?: $this->getDescription());
}
/**
* Sets the aliases for the command.
*
* @param string[] $aliases An array of aliases for the command
*
* @return $this
*
* @throws InvalidArgumentException When an alias is invalid
*/
public function setAliases(iterable $aliases): static
{
$list = [];
foreach ($aliases as $alias) {
$this->validateName($alias);
$list[] = $alias;
}
$this->aliases = \is_array($aliases) ? $aliases : $list;
return $this;
}
/**
* Returns the aliases for the command.
*/
public function getAliases(): array
{
return $this->aliases;
}
/**
* Returns the synopsis for the command.
*
* @param bool $short Whether to show the short version of the synopsis (with options folded) or not
*/
public function getSynopsis(bool $short = false): string
{
$key = $short ? 'short' : 'long';
if (!isset($this->synopsis[$key])) {
$this->synopsis[$key] = trim(sprintf('%s %s', $this->name, $this->definition->getSynopsis($short)));
}
return $this->synopsis[$key];
}
/**
* Add a command usage example, it'll be prefixed with the command name.
*
* @return $this
*/
public function addUsage(string $usage): static
{
if (!str_starts_with($usage, $this->name)) {
$usage = sprintf('%s %s', $this->name, $usage);
}
$this->usages[] = $usage;
return $this;
}
/**
* Returns alternative usages of the command.
*/
public function getUsages(): array
{
return $this->usages;
}
/**
* Gets a helper instance by name.
*
* @return HelperInterface
*
* @throws LogicException if no HelperSet is defined
* @throws InvalidArgumentException if the helper is not defined
*/
public function getHelper(string $name): mixed
{
if (null === $this->helperSet) {
throw new LogicException(sprintf('Cannot retrieve helper "%s" because there is no HelperSet defined. Did you forget to add your command to the application or to set the application on the command using the setApplication() method? You can also set the HelperSet directly using the setHelperSet() method.', $name));
}
return $this->helperSet->get($name);
}
/**
* Validates a command name.
*
* It must be non-empty and parts can optionally be separated by ":".
*
* @throws InvalidArgumentException When the name is invalid
*/
private function validateName(string $name): void
{
if (!preg_match('/^[^\:]++(\:[^\:]++)*$/', $name)) {
throw new InvalidArgumentException(sprintf('Command name "%s" is invalid.', $name));
}
}
}

View File

@@ -0,0 +1,223 @@
<?php
/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Symfony\Component\Console\Command;
use Symfony\Component\Console\Attribute\AsCommand;
use Symfony\Component\Console\Completion\CompletionInput;
use Symfony\Component\Console\Completion\CompletionSuggestions;
use Symfony\Component\Console\Completion\Output\BashCompletionOutput;
use Symfony\Component\Console\Completion\Output\CompletionOutputInterface;
use Symfony\Component\Console\Completion\Output\FishCompletionOutput;
use Symfony\Component\Console\Completion\Output\ZshCompletionOutput;
use Symfony\Component\Console\Exception\CommandNotFoundException;
use Symfony\Component\Console\Exception\ExceptionInterface;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Input\InputOption;
use Symfony\Component\Console\Output\OutputInterface;
/**
* Responsible for providing the values to the shell completion.
*
* @author Wouter de Jong <wouter@wouterj.nl>
*/
#[AsCommand(name: '|_complete', description: 'Internal command to provide shell completion suggestions')]
final class CompleteCommand extends Command
{
public const COMPLETION_API_VERSION = '1';
/**
* @deprecated since Symfony 6.1
*/
protected static $defaultName = '|_complete';
/**
* @deprecated since Symfony 6.1
*/
protected static $defaultDescription = 'Internal command to provide shell completion suggestions';
private array $completionOutputs;
private bool $isDebug = false;
/**
* @param array<string, class-string<CompletionOutputInterface>> $completionOutputs A list of additional completion outputs, with shell name as key and FQCN as value
*/
public function __construct(array $completionOutputs = [])
{
// must be set before the parent constructor, as the property value is used in configure()
$this->completionOutputs = $completionOutputs + [
'bash' => BashCompletionOutput::class,
'fish' => FishCompletionOutput::class,
'zsh' => ZshCompletionOutput::class,
];
parent::__construct();
}
protected function configure(): void
{
$this
->addOption('shell', 's', InputOption::VALUE_REQUIRED, 'The shell type ("'.implode('", "', array_keys($this->completionOutputs)).'")')
->addOption('input', 'i', InputOption::VALUE_REQUIRED | InputOption::VALUE_IS_ARRAY, 'An array of input tokens (e.g. COMP_WORDS or argv)')
->addOption('current', 'c', InputOption::VALUE_REQUIRED, 'The index of the "input" array that the cursor is in (e.g. COMP_CWORD)')
->addOption('api-version', 'a', InputOption::VALUE_REQUIRED, 'The API version of the completion script')
->addOption('symfony', 'S', InputOption::VALUE_REQUIRED, 'deprecated')
;
}
protected function initialize(InputInterface $input, OutputInterface $output): void
{
$this->isDebug = filter_var(getenv('SYMFONY_COMPLETION_DEBUG'), \FILTER_VALIDATE_BOOL);
}
protected function execute(InputInterface $input, OutputInterface $output): int
{
try {
// "symfony" must be kept for compat with the shell scripts generated by Symfony Console 5.4 - 6.1
$version = $input->getOption('symfony') ? '1' : $input->getOption('api-version');
if ($version && version_compare($version, self::COMPLETION_API_VERSION, '<')) {
$message = sprintf('Completion script version is not supported ("%s" given, ">=%s" required).', $version, self::COMPLETION_API_VERSION);
$this->log($message);
$output->writeln($message.' Install the Symfony completion script again by using the "completion" command.');
return 126;
}
$shell = $input->getOption('shell');
if (!$shell) {
throw new \RuntimeException('The "--shell" option must be set.');
}
if (!$completionOutput = $this->completionOutputs[$shell] ?? false) {
throw new \RuntimeException(sprintf('Shell completion is not supported for your shell: "%s" (supported: "%s").', $shell, implode('", "', array_keys($this->completionOutputs))));
}
$completionInput = $this->createCompletionInput($input);
$suggestions = new CompletionSuggestions();
$this->log([
'',
'<comment>'.date('Y-m-d H:i:s').'</>',
'<info>Input:</> <comment>("|" indicates the cursor position)</>',
' '.(string) $completionInput,
'<info>Command:</>',
' '.(string) implode(' ', $_SERVER['argv']),
'<info>Messages:</>',
]);
$command = $this->findCommand($completionInput, $output);
if (null === $command) {
$this->log(' No command found, completing using the Application class.');
$this->getApplication()->complete($completionInput, $suggestions);
} elseif (
$completionInput->mustSuggestArgumentValuesFor('command')
&& $command->getName() !== $completionInput->getCompletionValue()
&& !\in_array($completionInput->getCompletionValue(), $command->getAliases(), true)
) {
$this->log(' No command found, completing using the Application class.');
// expand shortcut names ("cache:cl<TAB>") into their full name ("cache:clear")
$suggestions->suggestValues(array_filter(array_merge([$command->getName()], $command->getAliases())));
} else {
$command->mergeApplicationDefinition();
$completionInput->bind($command->getDefinition());
if (CompletionInput::TYPE_OPTION_NAME === $completionInput->getCompletionType()) {
$this->log(' Completing option names for the <comment>'.($command instanceof LazyCommand ? $command->getCommand() : $command)::class.'</> command.');
$suggestions->suggestOptions($command->getDefinition()->getOptions());
} else {
$this->log([
' Completing using the <comment>'.($command instanceof LazyCommand ? $command->getCommand() : $command)::class.'</> class.',
' Completing <comment>'.$completionInput->getCompletionType().'</> for <comment>'.$completionInput->getCompletionName().'</>',
]);
if (null !== $compval = $completionInput->getCompletionValue()) {
$this->log(' Current value: <comment>'.$compval.'</>');
}
$command->complete($completionInput, $suggestions);
}
}
/** @var CompletionOutputInterface $completionOutput */
$completionOutput = new $completionOutput();
$this->log('<info>Suggestions:</>');
if ($options = $suggestions->getOptionSuggestions()) {
$this->log(' --'.implode(' --', array_map(fn ($o) => $o->getName(), $options)));
} elseif ($values = $suggestions->getValueSuggestions()) {
$this->log(' '.implode(' ', $values));
} else {
$this->log(' <comment>No suggestions were provided</>');
}
$completionOutput->write($suggestions, $output);
} catch (\Throwable $e) {
$this->log([
'<error>Error!</error>',
(string) $e,
]);
if ($output->isDebug()) {
throw $e;
}
return 2;
}
return 0;
}
private function createCompletionInput(InputInterface $input): CompletionInput
{
$currentIndex = $input->getOption('current');
if (!$currentIndex || !ctype_digit($currentIndex)) {
throw new \RuntimeException('The "--current" option must be set and it must be an integer.');
}
$completionInput = CompletionInput::fromTokens($input->getOption('input'), (int) $currentIndex);
try {
$completionInput->bind($this->getApplication()->getDefinition());
} catch (ExceptionInterface) {
}
return $completionInput;
}
private function findCommand(CompletionInput $completionInput, OutputInterface $output): ?Command
{
try {
$inputName = $completionInput->getFirstArgument();
if (null === $inputName) {
return null;
}
return $this->getApplication()->find($inputName);
} catch (CommandNotFoundException) {
}
return null;
}
private function log($messages): void
{
if (!$this->isDebug) {
return;
}
$commandName = basename($_SERVER['argv'][0]);
file_put_contents(sys_get_temp_dir().'/sf_'.$commandName.'.log', implode(\PHP_EOL, (array) $messages).\PHP_EOL, \FILE_APPEND);
}
}

View File

@@ -0,0 +1,161 @@
<?php
/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Symfony\Component\Console\Command;
use Symfony\Component\Console\Attribute\AsCommand;
use Symfony\Component\Console\Input\InputArgument;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Input\InputOption;
use Symfony\Component\Console\Output\ConsoleOutputInterface;
use Symfony\Component\Console\Output\OutputInterface;
use Symfony\Component\Process\Process;
/**
* Dumps the completion script for the current shell.
*
* @author Wouter de Jong <wouter@wouterj.nl>
*/
#[AsCommand(name: 'completion', description: 'Dump the shell completion script')]
final class DumpCompletionCommand extends Command
{
/**
* @deprecated since Symfony 6.1
*/
protected static $defaultName = 'completion';
/**
* @deprecated since Symfony 6.1
*/
protected static $defaultDescription = 'Dump the shell completion script';
private array $supportedShells;
protected function configure(): void
{
$fullCommand = $_SERVER['PHP_SELF'];
$commandName = basename($fullCommand);
$fullCommand = @realpath($fullCommand) ?: $fullCommand;
$shell = $this->guessShell();
[$rcFile, $completionFile] = match ($shell) {
'fish' => ['~/.config/fish/config.fish', "/etc/fish/completions/$commandName.fish"],
'zsh' => ['~/.zshrc', '$fpath[1]/_'.$commandName],
default => ['~/.bashrc', "/etc/bash_completion.d/$commandName"],
};
$supportedShells = implode(', ', $this->getSupportedShells());
$this
->setHelp(<<<EOH
The <info>%command.name%</> command dumps the shell completion script required
to use shell autocompletion (currently, {$supportedShells} completion are supported).
<comment>Static installation
-------------------</>
Dump the script to a global completion file and restart your shell:
<info>%command.full_name% {$shell} | sudo tee {$completionFile}</>
Or dump the script to a local file and source it:
<info>%command.full_name% {$shell} > completion.sh</>
<comment># source the file whenever you use the project</>
<info>source completion.sh</>
<comment># or add this line at the end of your "{$rcFile}" file:</>
<info>source /path/to/completion.sh</>
<comment>Dynamic installation
--------------------</>
Add this to the end of your shell configuration file (e.g. <info>"{$rcFile}"</>):
<info>eval "$({$fullCommand} completion {$shell})"</>
EOH
)
->addArgument('shell', InputArgument::OPTIONAL, 'The shell type (e.g. "bash"), the value of the "$SHELL" env var will be used if this is not given', null, $this->getSupportedShells(...))
->addOption('debug', null, InputOption::VALUE_NONE, 'Tail the completion debug log')
;
}
protected function execute(InputInterface $input, OutputInterface $output): int
{
$commandName = basename($_SERVER['argv'][0]);
if ($input->getOption('debug')) {
$this->tailDebugLog($commandName, $output);
return 0;
}
$shell = $input->getArgument('shell') ?? self::guessShell();
$completionFile = __DIR__.'/../Resources/completion.'.$shell;
if (!file_exists($completionFile)) {
$supportedShells = $this->getSupportedShells();
if ($output instanceof ConsoleOutputInterface) {
$output = $output->getErrorOutput();
}
if ($shell) {
$output->writeln(sprintf('<error>Detected shell "%s", which is not supported by Symfony shell completion (supported shells: "%s").</>', $shell, implode('", "', $supportedShells)));
} else {
$output->writeln(sprintf('<error>Shell not detected, Symfony shell completion only supports "%s").</>', implode('", "', $supportedShells)));
}
return 2;
}
$output->write(str_replace(['{{ COMMAND_NAME }}', '{{ VERSION }}'], [$commandName, CompleteCommand::COMPLETION_API_VERSION], file_get_contents($completionFile)));
return 0;
}
private static function guessShell(): string
{
return basename($_SERVER['SHELL'] ?? '');
}
private function tailDebugLog(string $commandName, OutputInterface $output): void
{
$debugFile = sys_get_temp_dir().'/sf_'.$commandName.'.log';
if (!file_exists($debugFile)) {
touch($debugFile);
}
$process = new Process(['tail', '-f', $debugFile], null, null, null, 0);
$process->run(function (string $type, string $line) use ($output): void {
$output->write($line);
});
}
/**
* @return string[]
*/
private function getSupportedShells(): array
{
if (isset($this->supportedShells)) {
return $this->supportedShells;
}
$shells = [];
foreach (new \DirectoryIterator(__DIR__.'/../Resources/') as $file) {
if (str_starts_with($file->getBasename(), 'completion.') && $file->isFile()) {
$shells[] = $file->getExtension();
}
}
sort($shells);
return $this->supportedShells = $shells;
}
}

View File

@@ -0,0 +1,82 @@
<?php
/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Symfony\Component\Console\Command;
use Symfony\Component\Console\Descriptor\ApplicationDescription;
use Symfony\Component\Console\Helper\DescriptorHelper;
use Symfony\Component\Console\Input\InputArgument;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Input\InputOption;
use Symfony\Component\Console\Output\OutputInterface;
/**
* HelpCommand displays the help for a given command.
*
* @author Fabien Potencier <fabien@symfony.com>
*/
class HelpCommand extends Command
{
private Command $command;
/**
* @return void
*/
protected function configure()
{
$this->ignoreValidationErrors();
$this
->setName('help')
->setDefinition([
new InputArgument('command_name', InputArgument::OPTIONAL, 'The command name', 'help', fn () => array_keys((new ApplicationDescription($this->getApplication()))->getCommands())),
new InputOption('format', null, InputOption::VALUE_REQUIRED, 'The output format (txt, xml, json, or md)', 'txt', fn () => (new DescriptorHelper())->getFormats()),
new InputOption('raw', null, InputOption::VALUE_NONE, 'To output raw command help'),
])
->setDescription('Display help for a command')
->setHelp(<<<'EOF'
The <info>%command.name%</info> command displays help for a given command:
<info>%command.full_name% list</info>
You can also output the help in other formats by using the <comment>--format</comment> option:
<info>%command.full_name% --format=xml list</info>
To display the list of available commands, please use the <info>list</info> command.
EOF
)
;
}
/**
* @return void
*/
public function setCommand(Command $command)
{
$this->command = $command;
}
protected function execute(InputInterface $input, OutputInterface $output): int
{
$this->command ??= $this->getApplication()->find($input->getArgument('command_name'));
$helper = new DescriptorHelper();
$helper->describe($output, $this->command, [
'format' => $input->getOption('format'),
'raw_text' => $input->getOption('raw'),
]);
unset($this->command);
return 0;
}
}

View File

@@ -0,0 +1,207 @@
<?php
/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Symfony\Component\Console\Command;
use Symfony\Component\Console\Application;
use Symfony\Component\Console\Completion\CompletionInput;
use Symfony\Component\Console\Completion\CompletionSuggestions;
use Symfony\Component\Console\Completion\Suggestion;
use Symfony\Component\Console\Helper\HelperInterface;
use Symfony\Component\Console\Helper\HelperSet;
use Symfony\Component\Console\Input\InputDefinition;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;
/**
* @author Nicolas Grekas <p@tchwork.com>
*/
final class LazyCommand extends Command
{
private \Closure|Command $command;
private ?bool $isEnabled;
public function __construct(string $name, array $aliases, string $description, bool $isHidden, \Closure $commandFactory, ?bool $isEnabled = true)
{
$this->setName($name)
->setAliases($aliases)
->setHidden($isHidden)
->setDescription($description);
$this->command = $commandFactory;
$this->isEnabled = $isEnabled;
}
public function ignoreValidationErrors(): void
{
$this->getCommand()->ignoreValidationErrors();
}
public function setApplication(?Application $application = null): void
{
if (1 > \func_num_args()) {
trigger_deprecation('symfony/console', '6.2', 'Calling "%s()" without any arguments is deprecated, pass null explicitly instead.', __METHOD__);
}
if ($this->command instanceof parent) {
$this->command->setApplication($application);
}
parent::setApplication($application);
}
public function setHelperSet(HelperSet $helperSet): void
{
if ($this->command instanceof parent) {
$this->command->setHelperSet($helperSet);
}
parent::setHelperSet($helperSet);
}
public function isEnabled(): bool
{
return $this->isEnabled ?? $this->getCommand()->isEnabled();
}
public function run(InputInterface $input, OutputInterface $output): int
{
return $this->getCommand()->run($input, $output);
}
public function complete(CompletionInput $input, CompletionSuggestions $suggestions): void
{
$this->getCommand()->complete($input, $suggestions);
}
public function setCode(callable $code): static
{
$this->getCommand()->setCode($code);
return $this;
}
/**
* @internal
*/
public function mergeApplicationDefinition(bool $mergeArgs = true): void
{
$this->getCommand()->mergeApplicationDefinition($mergeArgs);
}
public function setDefinition(array|InputDefinition $definition): static
{
$this->getCommand()->setDefinition($definition);
return $this;
}
public function getDefinition(): InputDefinition
{
return $this->getCommand()->getDefinition();
}
public function getNativeDefinition(): InputDefinition
{
return $this->getCommand()->getNativeDefinition();
}
/**
* @param array|\Closure(CompletionInput,CompletionSuggestions):list<string|Suggestion> $suggestedValues The values used for input completion
*/
public function addArgument(string $name, ?int $mode = null, string $description = '', mixed $default = null /* array|\Closure $suggestedValues = [] */): static
{
$suggestedValues = 5 <= \func_num_args() ? func_get_arg(4) : [];
$this->getCommand()->addArgument($name, $mode, $description, $default, $suggestedValues);
return $this;
}
/**
* @param array|\Closure(CompletionInput,CompletionSuggestions):list<string|Suggestion> $suggestedValues The values used for input completion
*/
public function addOption(string $name, string|array|null $shortcut = null, ?int $mode = null, string $description = '', mixed $default = null /* array|\Closure $suggestedValues = [] */): static
{
$suggestedValues = 6 <= \func_num_args() ? func_get_arg(5) : [];
$this->getCommand()->addOption($name, $shortcut, $mode, $description, $default, $suggestedValues);
return $this;
}
public function setProcessTitle(string $title): static
{
$this->getCommand()->setProcessTitle($title);
return $this;
}
public function setHelp(string $help): static
{
$this->getCommand()->setHelp($help);
return $this;
}
public function getHelp(): string
{
return $this->getCommand()->getHelp();
}
public function getProcessedHelp(): string
{
return $this->getCommand()->getProcessedHelp();
}
public function getSynopsis(bool $short = false): string
{
return $this->getCommand()->getSynopsis($short);
}
public function addUsage(string $usage): static
{
$this->getCommand()->addUsage($usage);
return $this;
}
public function getUsages(): array
{
return $this->getCommand()->getUsages();
}
public function getHelper(string $name): HelperInterface
{
return $this->getCommand()->getHelper($name);
}
public function getCommand(): parent
{
if (!$this->command instanceof \Closure) {
return $this->command;
}
$command = $this->command = ($this->command)();
$command->setApplication($this->getApplication());
if (null !== $this->getHelperSet()) {
$command->setHelperSet($this->getHelperSet());
}
$command->setName($this->getName())
->setAliases($this->getAliases())
->setHidden($this->isHidden())
->setDescription($this->getDescription());
// Will throw if the command is not correctly initialized.
$command->getDefinition();
return $command;
}
}

View File

@@ -0,0 +1,75 @@
<?php
/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Symfony\Component\Console\Command;
use Symfony\Component\Console\Descriptor\ApplicationDescription;
use Symfony\Component\Console\Helper\DescriptorHelper;
use Symfony\Component\Console\Input\InputArgument;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Input\InputOption;
use Symfony\Component\Console\Output\OutputInterface;
/**
* ListCommand displays the list of all available commands for the application.
*
* @author Fabien Potencier <fabien@symfony.com>
*/
class ListCommand extends Command
{
/**
* @return void
*/
protected function configure()
{
$this
->setName('list')
->setDefinition([
new InputArgument('namespace', InputArgument::OPTIONAL, 'The namespace name', null, fn () => array_keys((new ApplicationDescription($this->getApplication()))->getNamespaces())),
new InputOption('raw', null, InputOption::VALUE_NONE, 'To output raw command list'),
new InputOption('format', null, InputOption::VALUE_REQUIRED, 'The output format (txt, xml, json, or md)', 'txt', fn () => (new DescriptorHelper())->getFormats()),
new InputOption('short', null, InputOption::VALUE_NONE, 'To skip describing commands\' arguments'),
])
->setDescription('List commands')
->setHelp(<<<'EOF'
The <info>%command.name%</info> command lists all commands:
<info>%command.full_name%</info>
You can also display the commands for a specific namespace:
<info>%command.full_name% test</info>
You can also output the information in other formats by using the <comment>--format</comment> option:
<info>%command.full_name% --format=xml</info>
It's also possible to get raw list of commands (useful for embedding command runner):
<info>%command.full_name% --raw</info>
EOF
)
;
}
protected function execute(InputInterface $input, OutputInterface $output): int
{
$helper = new DescriptorHelper();
$helper->describe($output, $this->getApplication(), [
'format' => $input->getOption('format'),
'raw_text' => $input->getOption('raw'),
'namespace' => $input->getArgument('namespace'),
'short' => $input->getOption('short'),
]);
return 0;
}
}

View File

@@ -0,0 +1,68 @@
<?php
/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Symfony\Component\Console\Command;
use Symfony\Component\Console\Exception\LogicException;
use Symfony\Component\Lock\LockFactory;
use Symfony\Component\Lock\LockInterface;
use Symfony\Component\Lock\Store\FlockStore;
use Symfony\Component\Lock\Store\SemaphoreStore;
/**
* Basic lock feature for commands.
*
* @author Geoffrey Brier <geoffrey.brier@gmail.com>
*/
trait LockableTrait
{
private ?LockInterface $lock = null;
/**
* Locks a command.
*/
private function lock(?string $name = null, bool $blocking = false): bool
{
if (!class_exists(SemaphoreStore::class)) {
throw new LogicException('To enable the locking feature you must install the symfony/lock component. Try running "composer require symfony/lock".');
}
if (null !== $this->lock) {
throw new LogicException('A lock is already in place.');
}
if (SemaphoreStore::isSupported()) {
$store = new SemaphoreStore();
} else {
$store = new FlockStore();
}
$this->lock = (new LockFactory($store))->createLock($name ?: $this->getName());
if (!$this->lock->acquire($blocking)) {
$this->lock = null;
return false;
}
return true;
}
/**
* Releases the command lock if there is one.
*/
private function release(): void
{
if ($this->lock) {
$this->lock->release();
$this->lock = null;
}
}
}

View File

@@ -0,0 +1,34 @@
<?php
/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Symfony\Component\Console\Command;
/**
* Interface for command reacting to signal.
*
* @author Grégoire Pineau <lyrixx@lyrix.info>
*/
interface SignalableCommandInterface
{
/**
* Returns the list of signals to subscribe.
*/
public function getSubscribedSignals(): array;
/**
* The method will be called when the application is signaled.
*
* @param int|false $previousExitCode
*
* @return int|false The exit code to return or false to continue the normal execution
*/
public function handleSignal(int $signal, /* int|false $previousExitCode = 0 */);
}

View File

@@ -0,0 +1,356 @@
<?php
/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Symfony\Component\Console\Command;
use Symfony\Component\Console\Application;
use Symfony\Component\Console\Completion\CompletionInput;
use Symfony\Component\Console\Completion\CompletionSuggestions;
use Symfony\Component\Console\Helper\HelperInterface;
use Symfony\Component\Console\Helper\HelperSet;
use Symfony\Component\Console\Input\InputDefinition;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\ConsoleOutputInterface;
use Symfony\Component\Console\Output\OutputInterface;
use Symfony\Component\Stopwatch\Stopwatch;
/**
* @internal
*
* @author Jules Pietri <jules@heahprod.com>
*/
final class TraceableCommand extends Command implements SignalableCommandInterface
{
public readonly Command $command;
public int $exitCode;
public ?int $interruptedBySignal = null;
public bool $ignoreValidation;
public bool $isInteractive = false;
public string $duration = 'n/a';
public string $maxMemoryUsage = 'n/a';
public InputInterface $input;
public OutputInterface $output;
/** @var array<string, mixed> */
public array $arguments;
/** @var array<string, mixed> */
public array $options;
/** @var array<string, mixed> */
public array $interactiveInputs = [];
public array $handledSignals = [];
public function __construct(
Command $command,
private readonly Stopwatch $stopwatch,
) {
if ($command instanceof LazyCommand) {
$command = $command->getCommand();
}
$this->command = $command;
// prevent call to self::getDefaultDescription()
$this->setDescription($command->getDescription());
parent::__construct($command->getName());
// init below enables calling {@see parent::run()}
[$code, $processTitle, $ignoreValidationErrors] = \Closure::bind(function () {
return [$this->code, $this->processTitle, $this->ignoreValidationErrors];
}, $command, Command::class)();
if (\is_callable($code)) {
$this->setCode($code);
}
if ($processTitle) {
parent::setProcessTitle($processTitle);
}
if ($ignoreValidationErrors) {
parent::ignoreValidationErrors();
}
$this->ignoreValidation = $ignoreValidationErrors;
}
public function __call(string $name, array $arguments): mixed
{
return $this->command->{$name}(...$arguments);
}
public function getSubscribedSignals(): array
{
return $this->command instanceof SignalableCommandInterface ? $this->command->getSubscribedSignals() : [];
}
public function handleSignal(int $signal, int|false $previousExitCode = 0): int|false
{
if (!$this->command instanceof SignalableCommandInterface) {
return false;
}
$event = $this->stopwatch->start($this->getName().'.handle_signal');
$exit = $this->command->handleSignal($signal, $previousExitCode);
$event->stop();
if (!isset($this->handledSignals[$signal])) {
$this->handledSignals[$signal] = [
'handled' => 0,
'duration' => 0,
'memory' => 0,
];
}
++$this->handledSignals[$signal]['handled'];
$this->handledSignals[$signal]['duration'] += $event->getDuration();
$this->handledSignals[$signal]['memory'] = max(
$this->handledSignals[$signal]['memory'],
$event->getMemory() >> 20
);
return $exit;
}
/**
* {@inheritdoc}
*
* Calling parent method is required to be used in {@see parent::run()}.
*/
public function ignoreValidationErrors(): void
{
$this->ignoreValidation = true;
$this->command->ignoreValidationErrors();
parent::ignoreValidationErrors();
}
public function setApplication(?Application $application = null): void
{
$this->command->setApplication($application);
}
public function getApplication(): ?Application
{
return $this->command->getApplication();
}
public function setHelperSet(HelperSet $helperSet): void
{
$this->command->setHelperSet($helperSet);
}
public function getHelperSet(): ?HelperSet
{
return $this->command->getHelperSet();
}
public function isEnabled(): bool
{
return $this->command->isEnabled();
}
public function complete(CompletionInput $input, CompletionSuggestions $suggestions): void
{
$this->command->complete($input, $suggestions);
}
/**
* {@inheritdoc}
*
* Calling parent method is required to be used in {@see parent::run()}.
*/
public function setCode(callable $code): static
{
$this->command->setCode($code);
return parent::setCode(function (InputInterface $input, OutputInterface $output) use ($code): int {
$event = $this->stopwatch->start($this->getName().'.code');
$this->exitCode = $code($input, $output);
$event->stop();
return $this->exitCode;
});
}
/**
* @internal
*/
public function mergeApplicationDefinition(bool $mergeArgs = true): void
{
$this->command->mergeApplicationDefinition($mergeArgs);
}
public function setDefinition(array|InputDefinition $definition): static
{
$this->command->setDefinition($definition);
return $this;
}
public function getDefinition(): InputDefinition
{
return $this->command->getDefinition();
}
public function getNativeDefinition(): InputDefinition
{
return $this->command->getNativeDefinition();
}
public function addArgument(string $name, ?int $mode = null, string $description = '', mixed $default = null, array|\Closure $suggestedValues = []): static
{
$this->command->addArgument($name, $mode, $description, $default, $suggestedValues);
return $this;
}
public function addOption(string $name, string|array|null $shortcut = null, ?int $mode = null, string $description = '', mixed $default = null, array|\Closure $suggestedValues = []): static
{
$this->command->addOption($name, $shortcut, $mode, $description, $default, $suggestedValues);
return $this;
}
/**
* {@inheritdoc}
*
* Calling parent method is required to be used in {@see parent::run()}.
*/
public function setProcessTitle(string $title): static
{
$this->command->setProcessTitle($title);
return parent::setProcessTitle($title);
}
public function setHelp(string $help): static
{
$this->command->setHelp($help);
return $this;
}
public function getHelp(): string
{
return $this->command->getHelp();
}
public function getProcessedHelp(): string
{
return $this->command->getProcessedHelp();
}
public function getSynopsis(bool $short = false): string
{
return $this->command->getSynopsis($short);
}
public function addUsage(string $usage): static
{
$this->command->addUsage($usage);
return $this;
}
public function getUsages(): array
{
return $this->command->getUsages();
}
public function getHelper(string $name): HelperInterface
{
return $this->command->getHelper($name);
}
public function run(InputInterface $input, OutputInterface $output): int
{
$this->input = $input;
$this->output = $output;
$this->arguments = $input->getArguments();
$this->options = $input->getOptions();
$event = $this->stopwatch->start($this->getName(), 'command');
try {
$this->exitCode = parent::run($input, $output);
} finally {
$event->stop();
if ($output instanceof ConsoleOutputInterface && $output->isDebug()) {
$output->getErrorOutput()->writeln((string) $event);
}
$this->duration = $event->getDuration().' ms';
$this->maxMemoryUsage = ($event->getMemory() >> 20).' MiB';
if ($this->isInteractive) {
$this->extractInteractiveInputs($input->getArguments(), $input->getOptions());
}
}
return $this->exitCode;
}
protected function initialize(InputInterface $input, OutputInterface $output): void
{
$event = $this->stopwatch->start($this->getName().'.init', 'command');
$this->command->initialize($input, $output);
$event->stop();
}
protected function interact(InputInterface $input, OutputInterface $output): void
{
if (!$this->isInteractive = Command::class !== (new \ReflectionMethod($this->command, 'interact'))->getDeclaringClass()->getName()) {
return;
}
$event = $this->stopwatch->start($this->getName().'.interact', 'command');
$this->command->interact($input, $output);
$event->stop();
}
protected function execute(InputInterface $input, OutputInterface $output): int
{
$event = $this->stopwatch->start($this->getName().'.execute', 'command');
$exitCode = $this->command->execute($input, $output);
$event->stop();
return $exitCode;
}
private function extractInteractiveInputs(array $arguments, array $options): void
{
foreach ($arguments as $argName => $argValue) {
if (\array_key_exists($argName, $this->arguments) && $this->arguments[$argName] === $argValue) {
continue;
}
$this->interactiveInputs[$argName] = $argValue;
}
foreach ($options as $optName => $optValue) {
if (\array_key_exists($optName, $this->options) && $this->options[$optName] === $optValue) {
continue;
}
$this->interactiveInputs['--'.$optName] = $optValue;
}
}
}

View File

@@ -0,0 +1,38 @@
<?php
/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Symfony\Component\Console\CommandLoader;
use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Exception\CommandNotFoundException;
/**
* @author Robin Chalas <robin.chalas@gmail.com>
*/
interface CommandLoaderInterface
{
/**
* Loads a command.
*
* @throws CommandNotFoundException
*/
public function get(string $name): Command;
/**
* Checks if a command exists.
*/
public function has(string $name): bool;
/**
* @return string[]
*/
public function getNames(): array;
}

Some files were not shown because too many files have changed in this diff Show More