Compare commits

...

No commits in common. "main" and "v1.0.7" have entirely different histories.
main ... v1.0.7

16 changed files with 670 additions and 1452 deletions

View file

@ -1,7 +1,5 @@
# 文派统一插件发布 CI Workflow # 文派统一插件发布 CI Workflow
# 触发push tag v* # 触发push tag v*
# 运行环境forgejo-ci-php:latest (Alpine + php-cli + git + rsync + zip + node)
# 基于 ci-workflows/wp-release.yml 2026-02-18 版本
name: Release Plugin name: Release Plugin


on: on:
@ -18,47 +16,29 @@ jobs:
steps: steps:
- name: Checkout - name: Checkout
uses: actions/checkout@v4 uses: actions/checkout@v4
with:
fetch-depth: 0

- name: Verify tools
shell: bash
run: |
php -v | head -1 || true
git --version
rsync --version | head -1 || true
zip --version | head -2 || true
jq --version
curl --version | head -1 || true


- name: Extract version from tag - name: Extract version from tag
id: version id: version
shell: bash
run: | run: |
set -euo pipefail
TAG="${GITHUB_REF#refs/tags/}" TAG="${GITHUB_REF#refs/tags/}"
VERSION="${TAG#v}" VERSION="${TAG#v}"
echo "tag=$TAG" >> "$GITHUB_OUTPUT" echo "tag=$TAG" >> $GITHUB_OUTPUT
echo "version=$VERSION" >> "$GITHUB_OUTPUT" echo "version=$VERSION" >> $GITHUB_OUTPUT
echo "Tag: $TAG, Version: $VERSION" echo "Tag: $TAG, Version: $VERSION"


- name: Detect main plugin file - name: Detect main plugin file
id: detect id: detect
shell: bash
run: | run: |
set -euo pipefail
MAIN_FILE=$(grep -rl "Plugin Name:" *.php 2>/dev/null | head -1) MAIN_FILE=$(grep -rl "Plugin Name:" *.php 2>/dev/null | head -1)
if [ -z "$MAIN_FILE" ]; then if [ -z "$MAIN_FILE" ]; then
echo "::error::No main plugin file found" echo "::error::No main plugin file found"
exit 1 exit 1
fi fi
echo "main_file=$MAIN_FILE" >> "$GITHUB_OUTPUT" echo "main_file=$MAIN_FILE" >> $GITHUB_OUTPUT
echo "Main file: $MAIN_FILE" echo "Main file: $MAIN_FILE"


- name: Validate version consistency - name: Validate version consistency
shell: bash
run: | run: |
set -euo pipefail
VERSION="${{ steps.version.outputs.version }}" VERSION="${{ steps.version.outputs.version }}"
MAIN_FILE="${{ steps.detect.outputs.main_file }}" MAIN_FILE="${{ steps.detect.outputs.main_file }}"
HEADER_VERSION=$(grep -i "Version:" "$MAIN_FILE" | grep -v "Requires" | grep -v "Tested" | head -1 | sed "s/.*Version:[[:space:]]*//" | sed "s/[[:space:]]*$//" | tr -d "\r") HEADER_VERSION=$(grep -i "Version:" "$MAIN_FILE" | grep -v "Requires" | grep -v "Tested" | head -1 | sed "s/.*Version:[[:space:]]*//" | sed "s/[[:space:]]*$//" | tr -d "\r")
@ -76,62 +56,14 @@ jobs:
fi fi
echo "Version consistency check passed: $VERSION" echo "Version consistency check passed: $VERSION"


- name: Generate Changelog - name: Install dependencies
shell: bash
run: | run: |
set -euo pipefail apt-get update -qq && apt-get install -y -qq php-cli rsync zip > /dev/null 2>&1
TAG="${GITHUB_REF#refs/tags/}" php -v | head -1 || true

echo "rsync and zip installed"
PREV_TAG=$(git tag --sort=-version:refname | grep -E '^v' | grep -v "^${TAG}$" | head -1)

if [ -n "$PREV_TAG" ]; then
echo "Changelog: ${PREV_TAG}..${TAG}"
COMMITS=$(git log "${PREV_TAG}..${TAG}" --no-merges --pretty=format:"%s (%h)" 2>/dev/null || true)
else
echo "Changelog: first release, using all commits"
COMMITS=$(git log --no-merges --pretty=format:"%s (%h)" 2>/dev/null || true)
fi

if [ -z "$COMMITS" ]; then
: > /tmp/changelog.md
echo "No commits found for changelog"
exit 0
fi

FEAT="" FIX="" OTHER=""
while IFS= read -r line; do
case "$line" in
feat:*|feat\(*) FEAT="${FEAT}\n- ${line}" ;;
fix:*|fix\(*) FIX="${FIX}\n- ${line}" ;;
*) OTHER="${OTHER}\n- ${line}" ;;
esac
done <<< "$COMMITS"

CHANGELOG=""
HAS_CATEGORIES=false
if [ -n "$FEAT" ]; then
CHANGELOG="${CHANGELOG}#### New Features${FEAT}\n\n"
HAS_CATEGORIES=true
fi
if [ -n "$FIX" ]; then
CHANGELOG="${CHANGELOG}#### Bug Fixes${FIX}\n\n"
HAS_CATEGORIES=true
fi
if [ -n "$OTHER" ]; then
if [ "$HAS_CATEGORIES" = true ]; then
CHANGELOG="${CHANGELOG}#### Other Changes${OTHER}\n\n"
else
CHANGELOG="${OTHER#\\n}\n\n"
fi
fi

printf '%b' "$CHANGELOG" > /tmp/changelog.md
echo "Changelog generated ($(echo "$COMMITS" | wc -l) commits)"


- name: PHP Lint - name: PHP Lint
shell: bash
run: | run: |
set -euo pipefail
ERRORS=0 ERRORS=0
while IFS= read -r file; do while IFS= read -r file; do
if ! php -l "$file" > /dev/null 2>&1; then if ! php -l "$file" > /dev/null 2>&1; then
@ -139,7 +71,7 @@ jobs:
ERRORS=$((ERRORS + 1)) ERRORS=$((ERRORS + 1))
fi fi
done < <(find . -name "*.php" -not -path "./vendor/*" -not -path "./node_modules/*") done < <(find . -name "*.php" -not -path "./vendor/*" -not -path "./node_modules/*")
if [ "$ERRORS" -gt 0 ]; then if [ $ERRORS -gt 0 ]; then
echo "::error::PHP lint found $ERRORS error(s)" echo "::error::PHP lint found $ERRORS error(s)"
exit 1 exit 1
fi fi
@ -147,18 +79,13 @@ jobs:


- name: Build ZIP - name: Build ZIP
id: build id: build
shell: bash
run: | run: |
set -euo pipefail
VERSION="${{ steps.version.outputs.version }}" VERSION="${{ steps.version.outputs.version }}"
SLUG="${{ env.PLUGIN_SLUG }}" SLUG="${{ env.PLUGIN_SLUG }}"
ZIP_NAME="${SLUG}-${VERSION}.zip" ZIP_NAME="${SLUG}-${VERSION}.zip"
BUILD_DIR="/tmp/build/${SLUG}"
RELEASE_DIR="/tmp/release" RELEASE_DIR="/tmp/release"

mkdir -p /tmp/build/${SLUG}
rm -rf "$BUILD_DIR" "$RELEASE_DIR" mkdir -p ${RELEASE_DIR}
mkdir -p "$BUILD_DIR" "$RELEASE_DIR"

rsync -a \ rsync -a \
--exclude=".git" \ --exclude=".git" \
--exclude=".github" \ --exclude=".github" \
@ -167,13 +94,8 @@ jobs:
--exclude=".gitattributes" \ --exclude=".gitattributes" \
--exclude=".editorconfig" \ --exclude=".editorconfig" \
--exclude=".env*" \ --exclude=".env*" \
--exclude=".agent" \
--exclude=".vscode" \
--exclude="node_modules" \ --exclude="node_modules" \
--exclude="vendor" \
--exclude="tests" \ --exclude="tests" \
--exclude="docs" \
--exclude="lib" \
--exclude="phpunit.xml*" \ --exclude="phpunit.xml*" \
--exclude="phpcs.xml*" \ --exclude="phpcs.xml*" \
--exclude="phpstan.neon*" \ --exclude="phpstan.neon*" \
@ -186,251 +108,42 @@ jobs:
--exclude="*.md" \ --exclude="*.md" \
--exclude="LICENSE" \ --exclude="LICENSE" \
--exclude="Makefile" \ --exclude="Makefile" \
./ "$BUILD_DIR/" ./ /tmp/build/${SLUG}/

(
cd /tmp/build cd /tmp/build
zip -qr "${RELEASE_DIR}/${ZIP_NAME}" "${SLUG}/" zip -r ${RELEASE_DIR}/${ZIP_NAME} ${SLUG}/
) echo "zip_path=${RELEASE_DIR}/${ZIP_NAME}" >> $GITHUB_OUTPUT

echo "zip_name=${ZIP_NAME}" >> $GITHUB_OUTPUT
echo "zip_path=${RELEASE_DIR}/${ZIP_NAME}" >> "$GITHUB_OUTPUT" echo "release_dir=${RELEASE_DIR}" >> $GITHUB_OUTPUT
echo "zip_name=${ZIP_NAME}" >> "$GITHUB_OUTPUT" echo "Built: ${ZIP_NAME} ($(du -h ${RELEASE_DIR}/${ZIP_NAME} | cut -f1))"
echo "release_dir=${RELEASE_DIR}" >> "$GITHUB_OUTPUT"
echo "Built: ${ZIP_NAME} ($(du -h "${RELEASE_DIR}/${ZIP_NAME}" | cut -f1))"


- name: Calculate SHA-256 - name: Calculate SHA-256
id: checksum id: checksum
shell: bash
run: | run: |
set -euo pipefail
ZIP_PATH="${{ steps.build.outputs.zip_path }}" ZIP_PATH="${{ steps.build.outputs.zip_path }}"
ZIP_NAME="${{ steps.build.outputs.zip_name }}" ZIP_NAME="${{ steps.build.outputs.zip_name }}"
RELEASE_DIR="${{ steps.build.outputs.release_dir }}" RELEASE_DIR="${{ steps.build.outputs.release_dir }}"
SHA256=$(sha256sum "$ZIP_PATH" | cut -d" " -f1) SHA256=$(sha256sum "$ZIP_PATH" | cut -d" " -f1)
echo "$SHA256 $ZIP_NAME" > "${RELEASE_DIR}/${ZIP_NAME}.sha256" echo "$SHA256 $ZIP_NAME" > "${RELEASE_DIR}/${ZIP_NAME}.sha256"
echo "sha256=$SHA256" >> "$GITHUB_OUTPUT" echo "sha256=$SHA256" >> $GITHUB_OUTPUT
echo "SHA-256: $SHA256" echo "SHA-256: $SHA256"
echo "Release dir contents:"
ls -la "$RELEASE_DIR" ls -la "$RELEASE_DIR"


- name: Create or Update Release & Upload Assets - name: Create Release
shell: bash uses: actions/forgejo-release@v2
env: with:
RELEASE_TOKEN: ${{ secrets.RELEASE_TOKEN }} direction: upload
run: | url: https://feicode.com
set -euo pipefail token: ${{ secrets.RELEASE_TOKEN }}
tag: ${{ steps.version.outputs.tag }}
title: ${{ steps.version.outputs.tag }}
release-dir: ${{ steps.build.outputs.release_dir }}
verbose: true
release-notes: |
## ${{ env.PLUGIN_SLUG }} ${{ steps.version.outputs.tag }}


AUTH_TOKEN="${RELEASE_TOKEN:-${GITHUB_TOKEN:-}}" ### Checksums
if [ -z "$AUTH_TOKEN" ]; then
echo "::error::Missing auth token: set RELEASE_TOKEN or use default GITHUB_TOKEN"
exit 1
fi


TAG="${{ steps.version.outputs.tag }}" | File | SHA-256 |
SLUG="${{ env.PLUGIN_SLUG }}" |------|---------|
RELEASE_DIR="${{ steps.build.outputs.release_dir }}" | ${{ steps.build.outputs.zip_name }} | ${{ steps.checksum.outputs.sha256 }} |
ZIP_NAME="${{ steps.build.outputs.zip_name }}"
SHA256="${{ steps.checksum.outputs.sha256 }}"
API_URL="${GITHUB_SERVER_URL%/}/api/v1/repos/${GITHUB_REPOSITORY}"
AUTH_HEADER="Authorization: token ${AUTH_TOKEN}"

{
echo "## ${SLUG} ${TAG}"
echo ""
CHANGELOG_FILE="/tmp/changelog.md"
if [ -f "$CHANGELOG_FILE" ] && [ -s "$CHANGELOG_FILE" ]; then
echo "### What's Changed"
echo ""
cat "$CHANGELOG_FILE"
fi
echo "### Checksums"
echo ""
echo "| File | SHA-256 |"
echo "|------|---------|"
echo "| ${ZIP_NAME} | ${SHA256} |"
} > /tmp/release-notes.md
RELEASE_NOTES=$(cat /tmp/release-notes.md)

echo ">>> Resolving release ${TAG}"
STATUS=$(curl -sS -o /tmp/release.json -w "%{http_code}" \
-H "$AUTH_HEADER" \
"${API_URL}/releases/tags/${TAG}")

if [ "$STATUS" = "200" ]; then
RELEASE_ID=$(jq -r '.id' /tmp/release.json)
echo "Release exists (id=${RELEASE_ID}), patching metadata"
curl -sS -f -X PATCH \
-H "$AUTH_HEADER" \
-H "Content-Type: application/json" \
-d "$(jq -n --arg name "$TAG" --arg body "$RELEASE_NOTES" '{name: $name, body: $body, draft: false, prerelease: false}')" \
"${API_URL}/releases/${RELEASE_ID}" > /tmp/release.json
elif [ "$STATUS" = "404" ]; then
echo "Release not found, creating"
curl -sS -f -X POST \
-H "$AUTH_HEADER" \
-H "Content-Type: application/json" \
-d "$(jq -n --arg tag "$TAG" --arg name "$TAG" --arg body "$RELEASE_NOTES" '{tag_name: $tag, name: $name, body: $body, draft: false, prerelease: false}')" \
"${API_URL}/releases" > /tmp/release.json
else
echo "::error::Failed to query release (HTTP ${STATUS})"
cat /tmp/release.json
exit 1
fi

RELEASE_ID=$(jq -r '.id' /tmp/release.json)
if [ -z "$RELEASE_ID" ] || [ "$RELEASE_ID" = "null" ]; then
echo "::error::Failed to resolve release id"
cat /tmp/release.json
exit 1
fi

echo ">>> Uploading assets to release ${RELEASE_ID}"
for FILE in "${RELEASE_DIR}"/*; do
FILENAME=$(basename "$FILE")
EXISTING_ASSET_ID=$(jq -r --arg n "$FILENAME" '.assets[]? | select(.name == $n) | .id' /tmp/release.json | head -1)

if [ -n "$EXISTING_ASSET_ID" ] && [ "$EXISTING_ASSET_ID" != "null" ]; then
echo " deleting old asset: ${FILENAME} (id=${EXISTING_ASSET_ID})"
curl -sS -f -X DELETE \
-H "$AUTH_HEADER" \
"${API_URL}/releases/${RELEASE_ID}/assets/${EXISTING_ASSET_ID}" > /dev/null
fi

ENCODED_NAME=$(printf "%s" "$FILENAME" | jq -sRr @uri)
echo " uploading: ${FILENAME}"
curl -sS -f --retry 3 --retry-delay 2 --retry-all-errors \
-X POST \
-H "$AUTH_HEADER" \
-F "attachment=@${FILE}" \
"${API_URL}/releases/${RELEASE_ID}/assets?name=${ENCODED_NAME}" > /dev/null
done

echo ">>> Verifying uploaded assets"
curl -sS -f -H "$AUTH_HEADER" "${API_URL}/releases/${RELEASE_ID}" > /tmp/release-final.json
for FILE in "${RELEASE_DIR}"/*; do
FILENAME=$(basename "$FILE")
if ! jq -e --arg n "$FILENAME" '.assets[]? | select(.name == $n)' /tmp/release-final.json > /dev/null; then
echo "::error::Missing uploaded asset: ${FILENAME}"
jq -r '.assets[]?.name' /tmp/release-final.json
exit 1
fi
done

echo ">>> Release ${TAG} published successfully"
echo "Release URL: ${GITHUB_SERVER_URL%/}/${GITHUB_REPOSITORY}/releases/tag/${TAG}"

- name: Run post-release composer repair on target site (optional)
if: ${{ secrets.DEPLOY_HOST != '' && secrets.DEPLOY_SSH_KEY != '' }}
shell: bash
env:
DEPLOY_HOST: ${{ secrets.DEPLOY_HOST }}
DEPLOY_PORT: ${{ secrets.DEPLOY_PORT }}
DEPLOY_USER: ${{ secrets.DEPLOY_USER }}
DEPLOY_SSH_KEY: ${{ secrets.DEPLOY_SSH_KEY }}
DEPLOY_COMMAND_MODE: ${{ secrets.DEPLOY_COMMAND_MODE }}
DEPLOY_SITE_PATH: ${{ secrets.DEPLOY_SITE_PATH }}
DEPLOY_WP_USER: ${{ secrets.DEPLOY_WP_USER }}
DEPLOY_COMPOSER_SCRIPT: ${{ secrets.DEPLOY_COMPOSER_SCRIPT }}
run: |
set -euo pipefail

: "${DEPLOY_HOST:?DEPLOY_HOST is required when this step is enabled}"
DEPLOY_PORT="${DEPLOY_PORT:-22}"
DEPLOY_USER="${DEPLOY_USER:-wpdeploy}"
DEPLOY_COMMAND_MODE="${DEPLOY_COMMAND_MODE:-runner}"
SLUG="${{ env.PLUGIN_SLUG }}"

if ! command -v ssh >/dev/null 2>&1; then
if command -v apk >/dev/null 2>&1; then
apk add --no-cache openssh-client >/dev/null
else
echo "::error::ssh client not found in runner image"
exit 1
fi
fi

install -m 700 -d ~/.ssh
KEY_PATH="$HOME/.ssh/deploy_key"
printf '%s\n' "$DEPLOY_SSH_KEY" > "$KEY_PATH"
chmod 600 "$KEY_PATH"
ssh-keyscan -t rsa,ecdsa,ed25519 -p "$DEPLOY_PORT" -H "$DEPLOY_HOST" >> "$HOME/.ssh/known_hosts" 2>/dev/null || true

if [[ "$DEPLOY_COMMAND_MODE" == "runner" ]]; then
DEPLOY_COMPOSER_SCRIPT="${DEPLOY_COMPOSER_SCRIPT:-/usr/local/sbin/wp-post-release-composer-runner}"
ssh -i "$KEY_PATH" -p "$DEPLOY_PORT" -o BatchMode=yes -o StrictHostKeyChecking=yes "${DEPLOY_USER}@${DEPLOY_HOST}" \
"sudo '$DEPLOY_COMPOSER_SCRIPT' '$SLUG'"
else
DEPLOY_SITE_PATH="${DEPLOY_SITE_PATH:-/www/wwwroot/wptea.com}"
DEPLOY_WP_USER="${DEPLOY_WP_USER:-www}"
DEPLOY_COMPOSER_SCRIPT="${DEPLOY_COMPOSER_SCRIPT:-/opt/wenpai-infra/ops/wp-post-release-composer.sh}"
ssh -i "$KEY_PATH" -p "$DEPLOY_PORT" -o BatchMode=yes -o StrictHostKeyChecking=yes "${DEPLOY_USER}@${DEPLOY_HOST}" \
"bash '$DEPLOY_COMPOSER_SCRIPT' --site '$DEPLOY_SITE_PATH' --wp-user '$DEPLOY_WP_USER' --plugin '$SLUG' --strict"
fi

- name: Verify update API metadata (optional)
if: ${{ secrets.UPDATE_API_BASE != '' }}
shell: bash
env:
UPDATE_API_BASE: ${{ secrets.UPDATE_API_BASE }}
VERIFY_FROM_VERSION: ${{ secrets.VERIFY_FROM_VERSION }}
run: |
set -euo pipefail

API_BASE="${UPDATE_API_BASE%/}"
FROM_VERSION="${VERIFY_FROM_VERSION:-0.0.0}"
SLUG="${{ env.PLUGIN_SLUG }}"
MAIN_FILE="${{ steps.detect.outputs.main_file }}"
VERSION="${{ steps.version.outputs.version }}"
TAG="${{ steps.version.outputs.tag }}"
PLUGIN_FILE="${SLUG}/${MAIN_FILE}"

echo "Verify update-check: ${PLUGIN_FILE} from ${FROM_VERSION} -> ${VERSION}"
REQUEST_JSON=$(jq -cn --arg plugin_file "$PLUGIN_FILE" --arg from "$FROM_VERSION" '{plugins: {($plugin_file): {Version: $from}}}')

UPDATE_OK=0
for attempt in $(seq 1 36); do
curl -sS -f -X POST \
-H "Content-Type: application/json" \
--data "$REQUEST_JSON" \
"${API_BASE}/api/v1/update-check" > /tmp/update-check.json

API_VERSION=$(jq -r --arg plugin_file "$PLUGIN_FILE" '.plugins[$plugin_file].version // empty' /tmp/update-check.json)
API_PACKAGE=$(jq -r --arg plugin_file "$PLUGIN_FILE" '.plugins[$plugin_file].package // empty' /tmp/update-check.json)

if [[ "$API_VERSION" == "$VERSION" && "$API_PACKAGE" == *"/releases/download/${TAG}/"* ]]; then
UPDATE_OK=1
break
fi

echo "[attempt ${attempt}/36] update-check not ready, version=${API_VERSION:-<empty>} package=${API_PACKAGE:-<empty>}"
sleep 10
done

if [[ "$UPDATE_OK" -ne 1 ]]; then
echo "::error::update-check verification timeout"
cat /tmp/update-check.json
exit 1
fi

echo "Verify plugin info: ${SLUG}"
INFO_OK=0
for attempt in $(seq 1 36); do
curl -sS -f "${API_BASE}/api/v1/plugins/${SLUG}/info" > /tmp/plugin-info.json
INFO_VERSION=$(jq -r '.version // empty' /tmp/plugin-info.json)
INFO_PACKAGE=$(jq -r '.download_link // empty' /tmp/plugin-info.json)

if [[ "$INFO_VERSION" == "$VERSION" && "$INFO_PACKAGE" == *"/releases/download/${TAG}/"* ]]; then
INFO_OK=1
break
fi

echo "[attempt ${attempt}/36] plugin-info not ready, version=${INFO_VERSION:-<empty>} download=${INFO_PACKAGE:-<empty>}"
sleep 10
done

if [[ "$INFO_OK" -ne 1 ]]; then
echo "::error::plugin-info verification timeout"
cat /tmp/plugin-info.json
exit 1
fi

echo "Update API verification passed"

5
.gitignore vendored
View file

@ -1,5 +0,0 @@
vendor/
node_modules/
.env
*.log
.DS_Store

View file

@ -1,11 +0,0 @@
{
"id": "wpslug",
"name": "文派素格",
"tag": "SEO",
"tagClass": "",
"icon": "link",
"desc": "更友好美观的文章、页面、媒体别名,支持拼音和翻译等自动生成,告别中文乱码 URL。",
"landingPage": "/wp-admin/options-general.php?page=wpslug",
"pluginPath": "wpslug/wpslug.php",
"blogname": "文派素格体验站"
}

View file

@ -1,266 +0,0 @@
<?php
/**
* WenPai 插件更新器
*
* 为文派系插件提供自建更新服务支持。
* 通过文派云桥 (WenPai Bridge) 检查插件更新,
* 利用 WordPress 5.8+ 的 Update URI 机制。
*
* 当 wp-china-yes 插件激活并启用集中更新时,
* 此更新器会通过 wenpai_updater_override filter 自动让位。
*
* @package WenPai
* @version 1.0.0
* @requires WordPress 5.8+
* @requires PHP 7.4+
* @link https://feicode.com/WenPai-org
*/

if ( ! defined( 'ABSPATH' ) ) {
exit;
}

if ( class_exists( 'WenPai_Updater' ) ) {
return;
}

class WenPai_Updater {

/**
* 更新器版本号。
*
* @var string
*/
const VERSION = '1.1.1';

/**
* 云桥 API 地址。
*
* @var string
*/
const API_URL = 'https://updates.wenpai.net/api/v1';

/**
* 插件主文件 basename如 wpslug/wpslug.php
*
* @var string
*/
private $plugin_file;

/**
* 插件 slug如 wpslug
*
* @var string
*/
private $slug;

/**
* 当前插件版本。
*
* @var string
*/
private $version;

/**
* 初始化更新器。
*
* @param string $plugin_file 插件主文件路径plugin_basename 格式)。
* @param string $version 当前插件版本号。
*/
public function __construct( string $plugin_file, string $version ) {
$this->plugin_file = $plugin_file;
$this->slug = dirname( $plugin_file );
$this->version = $version;

// 检查是否被 wp-china-yes 集中更新接管
$is_overridden = apply_filters(
'wenpai_updater_override',
false,
$this->slug
);

if ( ! $is_overridden ) {
$this->register_hooks();
}
}

/**
* 注册 WordPress hooks。
*/
private function register_hooks(): void {
// Update URI: https://updates.wenpai.net 触发此 filter
add_filter(
'update_plugins_updates.wenpai.net',
[ $this, 'check_update' ],
10,
4
);

// 插件详情弹窗
add_filter( 'plugins_api', [ $this, 'plugin_info' ], 20, 3 );
}

/**
* 检查插件更新。
*
* WordPress 在检查更新时,对声明了 Update URI 的插件
* 触发 update_plugins_{hostname} filter。
*
* @param array|false $update 当前更新数据。
* @param array $plugin_data 插件头信息。
* @param string $plugin_file 插件文件路径。
* @param string[] $locales 语言列表。
* @return object|false 更新数据或 false。
*/
public function check_update( $update, array $plugin_data, string $plugin_file, array $locales ) {
if ( $plugin_file !== $this->plugin_file ) {
return $update;
}

$response = $this->api_request( 'update-check', [
'plugins' => [
$this->plugin_file => [
'Version' => $this->version,
],
],
] );

if ( is_wp_error( $response ) || empty( $response['plugins'][ $this->plugin_file ] ) ) {
return $update;
}

$data = $response['plugins'][ $this->plugin_file ];

return (object) [
'id' => $data['id'] ?? '',
'slug' => $data['slug'] ?? $this->slug,
'plugin' => $this->plugin_file,
'version' => $data['version'] ?? '',
'new_version' => $data['version'] ?? '',
'url' => $data['url'] ?? '',
'package' => $data['package'] ?? '',
'icons' => $data['icons'] ?? [],
'banners' => $data['banners'] ?? [],
'requires' => $data['requires'] ?? '',
'tested' => $data['tested'] ?? '',
'requires_php' => $data['requires_php'] ?? '',
];
}

/**
* 插件详情弹窗数据。
*
* 当用户在 WP 后台点击"查看详情"时触发。
*
* @param false|object|array $result 当前结果。
* @param string $action API 动作。
* @param object $args 请求参数。
* @return false|object 插件信息或 false。
*/
public function plugin_info( $result, string $action, object $args ) {
if ( 'plugin_information' !== $action ) {
return $result;
}

if ( ! isset( $args->slug ) || $args->slug !== $this->slug ) {
return $result;
}

$response = $this->api_request( "plugins/{$this->slug}/info" );

if ( ! is_wp_error( $response ) && ! isset( $response['error'] ) && ! empty( $response['name'] ) ) {
$info = new stdClass();
$info->name = $response['name'];
$info->slug = $response['slug'] ?? $this->slug;
$info->version = $response['version'] ?? '';
$info->author = $response['author'] ?? '';
$info->homepage = $response['homepage'] ?? '';
$info->download_link = $response['download_link'] ?? '';
$info->requires = $response['requires'] ?? '';
$info->tested = $response['tested'] ?? '';
$info->requires_php = $response['requires_php'] ?? '';
$info->last_updated = $response['last_updated'] ?? '';
$info->icons = $response['icons'] ?? [];
$info->banners = $response['banners'] ?? [];
$info->sections = $response['sections'] ?? [];
$info->external = true;

return $info;
}

// API 不可用或插件未注册时,用本地插件头信息兜底
$plugin_path = WP_PLUGIN_DIR . '/' . $this->plugin_file;
if ( ! file_exists( $plugin_path ) ) {
return $result;
}

if ( ! function_exists( 'get_plugin_data' ) ) {
require_once ABSPATH . 'wp-admin/includes/plugin.php';
}

$plugin_data = get_plugin_data( $plugin_path );

$info = new stdClass();
$info->name = $plugin_data['Name'] ?? $this->slug;
$info->slug = $this->slug;
$info->version = $this->version;
$info->author = $plugin_data['AuthorName'] ?? '';
$info->homepage = $plugin_data['PluginURI'] ?? '';
$info->requires = $plugin_data['RequiresWP'] ?? '';
$info->requires_php = $plugin_data['RequiresPHP'] ?? '';
$info->sections = [
'description' => $plugin_data['Description'] ?? '',
];
$info->external = true;

return $info;
}

/**
* 向云桥 API 发送请求。
*
* @param string $endpoint API 端点(不含 /api/v1/ 前缀)。
* @param array|null $body POST 请求体null 则用 GET
* @return array|WP_Error 解码后的响应或错误。
*/
private function api_request( string $endpoint, ?array $body = null ) {
$url = self::API_URL . '/' . ltrim( $endpoint, '/' );

$args = [
'timeout' => 10,
'headers' => [
'Accept' => 'application/json',
],
];

if ( null !== $body ) {
$args['headers']['Content-Type'] = 'application/json';
$args['body'] = wp_json_encode( $body );
$response = wp_remote_post( $url, $args );
} else {
$response = wp_remote_get( $url, $args );
}

if ( is_wp_error( $response ) ) {
return $response;
}

$code = wp_remote_retrieve_response_code( $response );
if ( 200 !== $code ) {
return new WP_Error(
'wenpai_bridge_error',
sprintf( 'WenPai Bridge API returned %d', $code )
);
}

$data = json_decode( wp_remote_retrieve_body( $response ), true );
if ( ! is_array( $data ) ) {
return new WP_Error(
'wenpai_bridge_parse_error',
'Invalid JSON response from WenPai Bridge'
);
}

return $data;
}
}

View file

@ -127,10 +127,10 @@ class WPSlug_Admin
<span style="font-size: 13px; padding-left: 10px;"> <span style="font-size: 13px; padding-left: 10px;">
<?php printf( esc_html__( 'Version: %s', 'wpslug' ), esc_html( WPSLUG_VERSION ) ); ?> <?php printf( esc_html__( 'Version: %s', 'wpslug' ), esc_html( WPSLUG_VERSION ) ); ?>
</span> </span>
<a href="https://wpcy.com/slug/" target="_blank" class="button button-secondary" style="margin-left: 10px;"> <a href="https://wpslug.com/document" target="_blank" class="button button-secondary" style="margin-left: 10px;">
<?php esc_html_e( 'Documentation', 'wpslug' ); ?> <?php esc_html_e( 'Documentation', 'wpslug' ); ?>
</a> </a>
<a href="https://wpcy.com/c/wpslug/" target="_blank" class="button button-secondary"> <a href="https://sharecms.com/forums/" target="_blank" class="button button-secondary">
<?php esc_html_e( 'Support', 'wpslug' ); ?> <?php esc_html_e( 'Support', 'wpslug' ); ?>
</a> </a>
</h1> </h1>
@ -740,35 +740,6 @@ class WPSlug_Admin
</tr> </tr>
</table> </table>
</div> </div>

<div class="wpslug-api-section" data-service="wpmind">
<h4><?php _e("WPMind AI Translation", "wpslug"); ?></h4>
<div class="wpslug-wpmind-status">
<?php if (function_exists('wpmind_is_available') && wpmind_is_available()): ?>
<p class="description" style="color: #2e7d32;">
<span class="dashicons dashicons-yes-alt"></span>
<?php _e("WPMind is active and configured. No additional settings required.", "wpslug"); ?>
</p>
<p class="description">
<?php _e("WPMind uses AI to translate titles to SEO-friendly slugs. It provides more accurate and context-aware translations compared to traditional translation services.", "wpslug"); ?>
</p>
<p class="description">
<a href="<?php echo admin_url('options-general.php?page=wpmind'); ?>">
<?php _e("Configure WPMind Settings", "wpslug"); ?> →
</a>
</p>
<?php else: ?>
<p class="description" style="color: #d32f2f;">
<span class="dashicons dashicons-warning"></span>
<?php _e("WPMind plugin is not active or not configured.", "wpslug"); ?>
</p>
<p class="description">
<?php _e("Please install and activate the WPMind plugin to use AI-powered translation.", "wpslug"); ?>
<a href="https://wpcy.com/mind/" target="_blank"><?php _e("Learn more", "wpslug"); ?></a>
</p>
<?php endif; ?>
</div>
</div>
</div> </div>
<?php <?php
} }

View file

@ -30,9 +30,6 @@ class WPSlug_Converter {
case 'pinyin': case 'pinyin':
$result = $this->convertPinyin($text, $options); $result = $this->convertPinyin($text, $options);
break; break;
case 'semantic_pinyin':
$result = $this->convertSemanticPinyin($text, $options);
break;
case 'transliteration': case 'transliteration':
$result = $this->convertTransliteration($text, $options); $result = $this->convertTransliteration($text, $options);
break; break;
@ -74,89 +71,6 @@ class WPSlug_Converter {
} }
} }


/**
* 语义化拼音转换(使用 WPMind AI
*
* 与普通拼音不同,这个方法会按词语分隔而非按字分隔
* 例如 "你好世界" → "nihao-shijie" 而非 "ni-hao-shi-jie"
*/
private function convertSemanticPinyin($text, $options) {
$debug_mode = isset($options['debug_mode']) && $options['debug_mode'];
try {
// 1. 检查是否是中文
if ($this->detectLanguage($text) !== 'zh') {
return $this->cleanBasicSlug($text, $options);
}

// 2. 检查 WPMind 是否可用
if (!function_exists('wpmind_pinyin') || !function_exists('wpmind_is_available') || !wpmind_is_available()) {
if ($debug_mode) {
error_log('[WPSlug] WPMind not available for semantic pinyin, falling back to regular pinyin');
}
return $this->convertPinyin($text, $options);
}

// 3. 文本长度限制(避免超时)
if (mb_strlen($text) > 200) {
if ($debug_mode) {
error_log('[WPSlug] Text too long for semantic pinyin, using regular pinyin');
}
return $this->convertPinyin($text, $options);
}

// 4. 调用 WPMind AI 进行语义化拼音转换
$result = wpmind_pinyin($text, [
'context' => 'wpslug_semantic_pinyin',
'cache_ttl' => 604800, // 7天
]);

// 5. 处理结果
if (is_wp_error($result)) {
if ($debug_mode) {
error_log('[WPSlug] WPMind pinyin error: ' . $result->get_error_message());
}
return $this->convertPinyin($text, $options);
}

// 6. 清理结果
$slug = $this->cleanSemanticPinyinResult($result, $options);

if (empty($slug)) {
if ($debug_mode) {
error_log('[WPSlug] WPMind returned empty pinyin, using regular pinyin');
}
return $this->convertPinyin($text, $options);
}

if ($debug_mode) {
error_log('[WPSlug] Semantic pinyin: "' . $text . '" → "' . $slug . '"');
}

return $slug;

} catch (Exception $e) {
$this->settings->logError('Semantic pinyin error: ' . $e->getMessage());
return $this->convertPinyin($text, $options);
}
}

/**
* 清理语义化拼音结果
*/
private function cleanSemanticPinyinResult($text, $options) {
// 移除可能的引号和空格
$text = trim($text, " \t\n\r\0\x0B\"'");
// 确保只有小写字母、数字和连字符
$text = preg_replace('/[^a-zA-Z0-9\-]/', '-', $text);
$text = strtolower($text);
$text = preg_replace('/-+/', '-', $text);
$text = trim($text, '-');
return $text;
}

private function convertTransliteration($text, $options) { private function convertTransliteration($text, $options) {
try { try {
$detected_lang = $this->detectLanguage($text); $detected_lang = $this->detectLanguage($text);
@ -249,7 +163,7 @@ class WPSlug_Converter {
} }


public function getSupportedModes() { public function getSupportedModes() {
return array('pinyin', 'semantic_pinyin', 'transliteration', 'translation'); return array('pinyin', 'transliteration', 'translation');
} }


public function isModeSupported($mode) { public function isModeSupported($mode) {

View file

@ -10,18 +10,6 @@ class WPSlug_Core {
private $optimizer; private $optimizer;
private $admin; private $admin;


/**
* Post types that should never have slug conversion applied.
* Covers ACF Pro / SCF internal types and other known plugin internals.
*/
private static $excluded_post_types = array(
'acf-field-group',
'acf-field',
'acf-post-type',
'acf-taxonomy',
'acf-ui-options-page',
);

public function __construct() { public function __construct() {
$this->settings = new WPSlug_Settings(); $this->settings = new WPSlug_Settings();
$this->converter = new WPSlug_Converter(); $this->converter = new WPSlug_Converter();
@ -53,12 +41,27 @@ class WPSlug_Core {
add_action('manage_pages_custom_column', array($this, 'displaySlugColumn'), 10, 2); add_action('manage_pages_custom_column', array($this, 'displaySlugColumn'), 10, 2);
} }
} }
/**
* Disabled: migrated to WPSlug_Updater (Update URI)
*/
private function init_update_checker() private function init_update_checker()
{ {
return; if (
file_exists(
plugin_dir_path(__FILE__) .
"../lib/plugin-update-checker/plugin-update-checker.php"
)
) {
require_once plugin_dir_path(__FILE__) .
"../lib/plugin-update-checker/plugin-update-checker.php";

if (
class_exists('YahnisElsts\PluginUpdateChecker\v5p3\PucFactory')
) {
$this->update_checker = \YahnisElsts\PluginUpdateChecker\v5p3\PucFactory::buildUpdateChecker(
"https://updates.weixiaoduo.com/wpslug.json",
WPSLUG_PLUGIN_DIR . "wpslug.php",
"wpslug"
);
}
}
} }


public function processSanitizeTitle($title, $raw_title = '', $context = 'display') { public function processSanitizeTitle($title, $raw_title = '', $context = 'display') {
@ -66,11 +69,6 @@ class WPSlug_Core {
return $title; return $title;
} }


// Skip when ACF internal post types are being saved
if ($this->isAcfInternalRequest()) {
return $title;
}

try { try {
$options = $this->settings->getOptions(); $options = $this->settings->getOptions();


@ -101,9 +99,6 @@ class WPSlug_Core {
} }


$post_type = $data['post_type']; $post_type = $data['post_type'];
if (in_array($post_type, self::$excluded_post_types, true)) {
return $data;
}
if (!$this->settings->isPostTypeEnabled($post_type)) { if (!$this->settings->isPostTypeEnabled($post_type)) {
return $data; return $data;
} }
@ -250,10 +245,6 @@ class WPSlug_Core {
return $slug; return $slug;
} }


if (in_array($post_type, self::$excluded_post_types, true)) {
return $slug;
}

if (!$this->settings->isPostTypeEnabled($post_type)) { if (!$this->settings->isPostTypeEnabled($post_type)) {
return $slug; return $slug;
} }
@ -314,10 +305,6 @@ class WPSlug_Core {
return; return;
} }


if (in_array($post->post_type, self::$excluded_post_types, true)) {
return;
}

if (!$this->settings->isPostTypeEnabled($post->post_type)) { if (!$this->settings->isPostTypeEnabled($post->post_type)) {
return; return;
} }
@ -407,38 +394,6 @@ class WPSlug_Core {
} }
} }


/**
* Detect if the current execution context is saving an ACF internal post type.
* Checks the call stack for ACF's internal post type class or field save functions.
*/
private function isAcfInternalRequest() {
if (function_exists('get_current_screen')) {
$screen = get_current_screen();
if ($screen && in_array($screen->post_type, self::$excluded_post_types, true)) {
return true;
}
}

$trace = debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS, 15);
foreach ($trace as $frame) {
if (isset($frame['class']) && strpos($frame['class'], 'ACF_Internal_Post_Type') !== false) {
return true;
}
if (isset($frame['class']) && strpos($frame['class'], 'ACF_Field_Group') !== false) {
return true;
}
if (isset($frame['function']) && in_array($frame['function'], array(
'acf_update_field',
'acf_import_field_group',
'acf_import_internal_post_type',
), true)) {
return true;
}
}

return false;
}

public function deactivate() { public function deactivate() {
flush_rewrite_rules(); flush_rewrite_rules();
} }

View file

@ -237,24 +237,14 @@ class WPSlug_Settings


public function getConversionModes() public function getConversionModes()
{ {
$modes = [ return [
"pinyin" => __("Chinese Pinyin Conversion", "wpslug"), "pinyin" => __("Chinese Pinyin Conversion", "wpslug"),
]; "transliteration" => __(
// 如果 WPMind 可用,添加语义化拼音选项
if (function_exists('wpmind_is_available') && wpmind_is_available()) {
$modes["semantic_pinyin"] = __("Semantic Pinyin (WPMind AI)", "wpslug");
} elseif (class_exists('\\WPMind\\WPMind')) {
$modes["semantic_pinyin"] = __("Semantic Pinyin (Requires WPMind)", "wpslug");
}
$modes["transliteration"] = __(
"Foreign Language Transliteration", "Foreign Language Transliteration",
"wpslug" "wpslug"
); ),
$modes["translation"] = __("Multi-language Translation", "wpslug"); "translation" => __("Multi-language Translation", "wpslug"),
];
return $modes;
} }


public function getTransliterationMethods() public function getTransliterationMethods()
@ -276,25 +266,11 @@ class WPSlug_Settings


public function getTranslationServices() public function getTranslationServices()
{ {
$services = [ return [
"none" => __("None", "wpslug"), "none" => __("None", "wpslug"),
"google" => __("Google Translate", "wpslug"), "google" => __("Google Translate", "wpslug"),
"baidu" => __("Baidu Translate", "wpslug"), "baidu" => __("Baidu Translate", "wpslug"),
]; ];
// 动态检测 WPMind 是否可用
if (function_exists('wpmind_is_available') && wpmind_is_available()) {
// WPMind 可用,添加到服务列表顶部(推荐)
$services = array_merge(
["wpmind" => __("WPMind AI (Recommended)", "wpslug")],
$services
);
} elseif (class_exists('\\WPMind\\WPMind')) {
// WPMind 已安装但未配置
$services["wpmind"] = __("WPMind AI (Not Configured)", "wpslug");
}
return $services;
} }


public function getLanguages() public function getLanguages()
@ -376,16 +352,6 @@ class WPSlug_Settings


public function isPostTypeEnabled($post_type) public function isPostTypeEnabled($post_type)
{ {
$excluded = array(
'acf-field-group',
'acf-field',
'acf-post-type',
'acf-taxonomy',
'acf-ui-options-page',
);
if (in_array($post_type, $excluded, true)) {
return false;
}
$enabled_post_types = $this->getOption("enabled_post_types", []); $enabled_post_types = $this->getOption("enabled_post_types", []);
return empty($enabled_post_types) || return empty($enabled_post_types) ||
in_array($post_type, $enabled_post_types); in_array($post_type, $enabled_post_types);

View file

@ -7,15 +7,6 @@ if (!defined('ABSPATH')) {
class WPSlug_Translator { class WPSlug_Translator {
private $converter; private $converter;


/**
* 防止循环调用的静态标志
* 当使用 WPMind 翻译时WPMind 内部可能触发 sanitize_title filter
* 如果没有保护,会导致无限递归
*
* @var bool
*/
private static $is_translating = false;

public function __construct() { public function __construct() {
$this->converter = null; $this->converter = null;
} }
@ -25,23 +16,9 @@ class WPSlug_Translator {
return ''; return '';
} }


// 防止循环调用:如果正在翻译中,直接回退到拼音
if (self::$is_translating) {
return $this->fallbackTranslate($text, $options);
}

$service = isset($options['translation_service']) ? $options['translation_service'] : 'none'; $service = isset($options['translation_service']) ? $options['translation_service'] : 'none';
switch ($service) { switch ($service) {
case 'wpmind':
// WPMind 服务需要循环保护
self::$is_translating = true;
try {
$result = $this->translateWPMind($text, $options);
} finally {
self::$is_translating = false;
}
return $result;
case 'google': case 'google':
return $this->translateGoogle($text, $options); return $this->translateGoogle($text, $options);
case 'baidu': case 'baidu':
@ -189,96 +166,6 @@ class WPSlug_Translator {
} }
} }


/**
* 使用 WPMind AI 翻译
*
* @param string $text 要翻译的文本
* @param array $options 选项
* @return string 翻译后的文本slug 格式)
*/
private function translateWPMind($text, $options) {
$debug_mode = isset($options['debug_mode']) && $options['debug_mode'];
// 获取语言设置(提前获取以便用于缓存键)
$source_lang = isset($options['translation_source_lang']) ? $options['translation_source_lang'] : 'zh';
$target_lang = isset($options['translation_target_lang']) ? $options['translation_target_lang'] : 'en';
// 1. 先检查本地缓存(缓存键包含语言设置)
$cache_key = 'wpslug_wpmind_' . md5($text . '_' . $source_lang . '_' . $target_lang);
$cached = get_transient($cache_key);
if ($cached !== false) {
if ($debug_mode) {
error_log('[WPSlug] WPMind cache hit for: ' . $text . ' (' . $source_lang . ' -> ' . $target_lang . ')');
}
return $cached;
}

// 2. 检查 WPMind 是否可用
if (!function_exists('wpmind_is_available') || !wpmind_is_available()) {
if ($debug_mode) {
error_log('[WPSlug] WPMind not available, falling back to pinyin');
}
return $this->fallbackTranslate($text, $options);
}

// 3. 文本长度限制(避免超时)
if (mb_strlen($text) > 200) {
if ($debug_mode) {
error_log('[WPSlug] Text too long (' . mb_strlen($text) . ' chars), using pinyin');
}
return $this->fallbackTranslate($text, $options);
}

// 4. 中文字符数限制
$chinese_count = preg_match_all('/[\x{4e00}-\x{9fff}]/u', $text);
if ($chinese_count > 50) {
if ($debug_mode) {
error_log('[WPSlug] Too many Chinese characters (' . $chinese_count . '), using pinyin');
}
return $this->fallbackTranslate($text, $options);
}

// 5. 调用 WPMind API语言设置已在前面获取
$start_time = microtime(true);
$result = wpmind_translate($text, $source_lang, $target_lang, [
'context' => 'wpslug_translation',
'format' => 'slug',
'cache_ttl' => 86400, // WPMind 内部缓存 1 天
'max_tokens' => 100,
'temperature' => 0.3,
]);

$elapsed_time = round((microtime(true) - $start_time) * 1000);

// 7. 处理结果
if (is_wp_error($result)) {
if ($debug_mode) {
error_log('[WPSlug] WPMind error: ' . $result->get_error_message() . ' (took ' . $elapsed_time . 'ms)');
}
return $this->fallbackTranslate($text, $options);
}

$slug = $this->cleanTranslatedText($result);

// 8. 验证结果有效性
if (empty($slug)) {
if ($debug_mode) {
error_log('[WPSlug] WPMind returned empty result, using pinyin');
}
return $this->fallbackTranslate($text, $options);
}

// 9. 缓存结果7 天)
set_transient($cache_key, $slug, 7 * DAY_IN_SECONDS);

if ($debug_mode) {
error_log('[WPSlug] WPMind translated "' . $text . '" to "' . $slug . '" in ' . $elapsed_time . 'ms');
}

return $slug;
}

private function fallbackTranslate($text, $options) { private function fallbackTranslate($text, $options) {
if ($this->converter === null) { if ($this->converter === null) {
$this->converter = new WPSlug_Converter(); $this->converter = new WPSlug_Converter();

View file

@ -0,0 +1,200 @@
<?php
/**
* WPSlug 自动更新器
*
* 通过文派云桥 (WenPai Bridge) 检查插件更新。
* 利用 WordPress 5.8+ 的 Update URI 机制,注册
* update_plugins_updates.wenpai.net filter。
*
* @package WPSlug
*/

if (!defined("ABSPATH")) {
exit();
}

class WPSlug_Updater
{
/** @var string 云桥 API 地址 */
private $api_url = "https://updates.wenpai.net/api/v1";

/** @var string 插件主文件 basename */
private $plugin_file;

/** @var string 插件 slug */
private $slug;

/** @var string 当前版本 */
private $version;

/**
* 初始化更新器。
*
* @param string $plugin_file 插件主文件路径plugin_basename 格式)
* @param string $version 当前插件版本
*/
public function __construct(string $plugin_file, string $version)
{
$this->plugin_file = $plugin_file;
$this->slug = dirname($plugin_file);
$this->version = $version;

$this->register_hooks();
}

/**
* 注册 WordPress hooks。
*/
private function register_hooks(): void
{
// Update URI: https://updates.wenpai.net 触发此 filter
add_filter(
"update_plugins_updates.wenpai.net",
[$this, "check_update"],
10,
4
);

// 插件详情弹窗
add_filter("plugins_api", [$this, "plugin_info"], 20, 3);
}

/**
* 检查插件更新。
*
* WordPress 在检查更新时,对声明了 Update URI 的插件
* 触发 update_plugins_{hostname} filter。
*
* @param array|false $update 当前更新数据
* @param array $plugin_data 插件头信息
* @param string $plugin_file 插件文件路径
* @param string[] $locales 语言列表
* @return array|false 更新数据或 false
*/
public function check_update($update, array $plugin_data, string $plugin_file, array $locales)
{
if ($plugin_file !== $this->plugin_file) {
return $update;
}

$response = $this->api_request("update-check", [
"plugins" => [
$this->plugin_file => [
"Version" => $this->version,
],
],
]);

if (is_wp_error($response) || empty($response["plugins"][$this->plugin_file])) {
return $update;
}

$data = $response["plugins"][$this->plugin_file];

return (object) [
"slug" => $data["slug"] ?? $this->slug,
"plugin" => $this->plugin_file,
"new_version" => $data["version"] ?? "",
"url" => $data["url"] ?? "",
"package" => $data["package"] ?? "",
"icons" => $data["icons"] ?? [],
"banners" => $data["banners"] ?? [],
"requires" => $data["requires"] ?? "",
"tested" => $data["tested"] ?? "",
"requires_php" => $data["requires_php"] ?? "",
];
}

/**
* 插件详情弹窗数据。
*
* 当用户在 WP 后台点击"查看详情"时触发。
*
* @param false|object|array $result 当前结果
* @param string $action API 动作
* @param object $args 请求参数
* @return false|object 插件信息或 false
*/
public function plugin_info($result, string $action, object $args)
{
if ($action !== "plugin_information") {
return $result;
}

if (!isset($args->slug) || $args->slug !== $this->slug) {
return $result;
}

$response = $this->api_request("plugins/{$this->slug}/info");

if (is_wp_error($response)) {
return $result;
}

$info = new \stdClass();
$info->name = $response["name"] ?? "";
$info->slug = $response["slug"] ?? $this->slug;
$info->version = $response["version"] ?? "";
$info->author = $response["author"] ?? "";
$info->homepage = $response["homepage"] ?? "";
$info->download_link = $response["download_link"] ?? "";
$info->requires = $response["requires"] ?? "";
$info->tested = $response["tested"] ?? "";
$info->requires_php = $response["requires_php"] ?? "";
$info->last_updated = $response["last_updated"] ?? "";
$info->icons = $response["icons"] ?? [];
$info->banners = $response["banners"] ?? [];
$info->sections = $response["sections"] ?? [];

return $info;
}

/**
* 向云桥 API 发送请求。
*
* @param string $endpoint API 端点(不含 /api/v1/ 前缀)
* @param array|null $body POST 请求体null 则用 GET
* @return array|\WP_Error 解码后的响应或错误
*/
private function api_request(string $endpoint, ?array $body = null)
{
$url = rtrim($this->api_url, "/") . "/" . ltrim($endpoint, "/");

$args = [
"timeout" => 15,
"headers" => [
"Accept" => "application/json",
],
];

if ($body !== null) {
$args["headers"]["Content-Type"] = "application/json";
$args["body"] = wp_json_encode($body);
$response = wp_remote_post($url, $args);
} else {
$response = wp_remote_get($url, $args);
}

if (is_wp_error($response)) {
return $response;
}

$code = wp_remote_retrieve_response_code($response);
if ($code !== 200) {
return new \WP_Error(
"wenpai_bridge_error",
sprintf("WenPai Bridge API returned %d", $code)
);
}

$data = json_decode(wp_remote_retrieve_body($response), true);
if (!is_array($data)) {
return new \WP_Error(
"wenpai_bridge_parse_error",
"Invalid JSON response from WenPai Bridge"
);
}

return $data;
}
}

View file

@ -130,13 +130,12 @@ class WPSlug_Validator {
} }
public static function validateConversionMode($mode) { public static function validateConversionMode($mode) {
$valid_modes = array('pinyin', 'semantic_pinyin', 'transliteration', 'translation'); $valid_modes = array('pinyin', 'transliteration', 'translation');
return self::validateSelect($mode, $valid_modes, 'pinyin'); return self::validateSelect($mode, $valid_modes, 'pinyin');
} }
public static function validateTranslationService($service) { public static function validateTranslationService($service) {
// 注意wpmind 服务需要在此列表中才能保存 $valid_services = array('none', 'google', 'baidu');
$valid_services = array('none', 'google', 'baidu', 'wpmind');
return self::validateSelect($service, $valid_services, 'none'); return self::validateSelect($service, $valid_services, 'none');
} }
@ -158,15 +157,6 @@ class WPSlug_Validator {
if ($service === 'baidu' && (empty($options['baidu_app_id']) || empty($options['baidu_secret_key']))) { if ($service === 'baidu' && (empty($options['baidu_app_id']) || empty($options['baidu_secret_key']))) {
$errors[] = __('Baidu App ID and Secret Key are required for Baidu Translate service.', 'wpslug'); $errors[] = __('Baidu App ID and Secret Key are required for Baidu Translate service.', 'wpslug');
} }
// WPMind 需要已配置
if ($service === 'wpmind') {
if (!function_exists('wpmind_is_available')) {
$errors[] = __('WPMind plugin is not installed.', 'wpslug');
} elseif (!wpmind_is_available()) {
$errors[] = __('WPMind is not configured. Please configure it in WPMind settings.', 'wpslug');
}
}
} }
return empty($errors) ? true : $errors; return empty($errors) ? true : $errors;

File diff suppressed because one or more lines are too long

Binary file not shown.

View file

@ -1,9 +1,8 @@
msgid "" msgid ""
msgstr "" msgstr ""
"Project-Id-Version: WPSlug\n" "Project-Id-Version: WPSlug\n"
"Report-Msgid-Bugs-To: https://wordpress.org/support/plugin/wpslug\n" "POT-Creation-Date: 2025-07-13 19:54+0800\n"
"POT-Creation-Date: 2026-02-28T15:19:21+08:00\n" "PO-Revision-Date: 2025-07-13 20:30+0800\n"
"PO-Revision-Date: 2026-02-28 15:20+0800\n"
"Last-Translator: \n" "Last-Translator: \n"
"Language-Team: \n" "Language-Team: \n"
"Language: zh_CN\n" "Language: zh_CN\n"
@ -15,36 +14,16 @@ msgstr ""
"X-Poedit-Flags-xgettext: --add-comments=translators:\n" "X-Poedit-Flags-xgettext: --add-comments=translators:\n"
"X-Poedit-WPHeader: wpslug.php\n" "X-Poedit-WPHeader: wpslug.php\n"
"X-Poedit-SourceCharset: UTF-8\n" "X-Poedit-SourceCharset: UTF-8\n"
"X-Poedit-KeywordsList: __;_e;_n:1,2;_x:1,2c;_ex:1,2c;_nx:4c,1,2;esc_attr__;" "X-Poedit-KeywordsList: "
"esc_attr_e;esc_attr_x:1,2c;esc_html__;esc_html_e;esc_html_x:1,2c;_n_noop:1,2;" "__;_e;_n:1,2;_x:1,2c;_ex:1,2c;_nx:4c,1,2;esc_attr__;esc_attr_e;esc_attr_x:1,2c;esc_html__;esc_html_e;esc_html_x:1,2c;_n_noop:1,2;_nx_noop:3c,1,2;__ngettext_noop:1,2\n"
"_nx_noop:3c,1,2;__ngettext_noop:1,2\n"
"X-Poedit-SearchPath-0: .\n" "X-Poedit-SearchPath-0: .\n"
"X-Poedit-SearchPathExcluded-0: *.min.js\n" "X-Poedit-SearchPathExcluded-0: *.min.js\n"


#. Plugin Name of the plugin
#. Author of the plugin
#: wpslug.php
msgid "WPSlug"
msgstr "文派素格"

#. Plugin URI of the plugin
#. Author URI of the plugin
#: wpslug.php
msgid "https://wpcy.com/slug"
msgstr "https://wpcy.com/slug"

#. Description of the plugin
#: wpslug.php
msgid ""
"Advanced slug management plugin with Chinese Pinyin support and SEO "
"optimization."
msgstr "具有中文拼音支持和 SEO 优化的高级别名管理插件。"

#: includes/class-wpslug-admin.php:56 #: includes/class-wpslug-admin.php:56
msgid "WPSlug Settings" msgid "WPSlug Settings"
msgstr "文派别名设置" msgstr "文派别名设置"


#: includes/class-wpslug-admin.php:57 includes/class-wpslug-core.php:346 #: includes/class-wpslug-admin.php:57 includes/class-wpslug-core.php:310
msgid "Slug" msgid "Slug"
msgstr "别名" msgstr "别名"


@ -52,7 +31,7 @@ msgstr "别名"
msgid "Settings saved successfully!" msgid "Settings saved successfully!"
msgstr "设置保存成功!" msgstr "设置保存成功!"


#: includes/class-wpslug-admin.php:112 #: includes/class-wpslug-admin.php:113
msgid "You do not have sufficient permissions to access this page." msgid "You do not have sufficient permissions to access this page."
msgstr "您没有足够的权限访问此页面。" msgstr "您没有足够的权限访问此页面。"


@ -89,11 +68,11 @@ msgstr "转写"
msgid "Translation" msgid "Translation"
msgstr "翻译" msgstr "翻译"


#: includes/class-wpslug-admin.php:188 includes/class-wpslug-admin.php:780 #: includes/class-wpslug-admin.php:188 includes/class-wpslug-admin.php:751
msgid "SEO Optimization" msgid "SEO Optimization"
msgstr "SEO 优化" msgstr "SEO 优化"


#: includes/class-wpslug-admin.php:194 includes/class-wpslug-admin.php:941 #: includes/class-wpslug-admin.php:194 includes/class-wpslug-admin.php:912
msgid "Media Files" msgid "Media Files"
msgstr "媒体文件" msgstr "媒体文件"


@ -114,15 +93,15 @@ msgid "Debug Checkboxes"
msgstr "调试复选框" msgstr "调试复选框"


#: includes/class-wpslug-admin.php:277 includes/class-wpslug-admin.php:290 #: includes/class-wpslug-admin.php:277 includes/class-wpslug-admin.php:290
#: includes/class-wpslug-admin.php:1294 #: includes/class-wpslug-admin.php:1265
msgid "Preview" msgid "Preview"
msgstr "预览" msgstr "预览"


#: includes/class-wpslug-admin.php:279 #: includes/class-wpslug-admin.php:280
msgid "Test your conversion settings with live preview." msgid "Test your conversion settings with live preview."
msgstr "通过实时预览测试您的转换设置。" msgstr "通过实时预览测试您的转换设置。"


#: includes/class-wpslug-admin.php:285 #: includes/class-wpslug-admin.php:286
msgid "Enter text to preview conversion..." msgid "Enter text to preview conversion..."
msgstr "输入文本以预览转换..." msgstr "输入文本以预览转换..."


@ -130,7 +109,7 @@ msgstr "输入文本以预览转换..."
msgid "General Settings" msgid "General Settings"
msgstr "常规设置" msgstr "常规设置"


#: includes/class-wpslug-admin.php:306 #: includes/class-wpslug-admin.php:307
msgid "Configure basic plugin behavior and choose your conversion method." msgid "Configure basic plugin behavior and choose your conversion method."
msgstr "配置基本插件行为并选择您的转换方法。" msgstr "配置基本插件行为并选择您的转换方法。"


@ -138,7 +117,7 @@ msgstr "配置基本插件行为并选择您的转换方法。"
msgid "Enable Plugin" msgid "Enable Plugin"
msgstr "启用插件" msgstr "启用插件"


#: includes/class-wpslug-admin.php:326 #: includes/class-wpslug-admin.php:327
msgid "Enable automatic slug conversion for your content" msgid "Enable automatic slug conversion for your content"
msgstr "为您的内容启用自动别名转换" msgstr "为您的内容启用自动别名转换"


@ -146,7 +125,7 @@ msgstr "为您的内容启用自动别名转换"
msgid "Conversion Mode" msgid "Conversion Mode"
msgstr "转换模式" msgstr "转换模式"


#: includes/class-wpslug-admin.php:352 #: includes/class-wpslug-admin.php:353
msgid "" msgid ""
"Select the conversion method. Pinyin for Chinese, Transliteration for " "Select the conversion method. Pinyin for Chinese, Transliteration for "
"Cyrillic/Arabic scripts, Translation for other languages." "Cyrillic/Arabic scripts, Translation for other languages."
@ -157,7 +136,7 @@ msgstr ""
msgid "Auto Convert" msgid "Auto Convert"
msgstr "自动转换" msgstr "自动转换"


#: includes/class-wpslug-admin.php:368 #: includes/class-wpslug-admin.php:369
msgid "Automatically convert slugs when saving posts and terms" msgid "Automatically convert slugs when saving posts and terms"
msgstr "保存文章和术语时自动转换别名" msgstr "保存文章和术语时自动转换别名"


@ -165,7 +144,7 @@ msgstr "保存文章和术语时自动转换别名"
msgid "Force Lowercase" msgid "Force Lowercase"
msgstr "强制小写" msgstr "强制小写"


#: includes/class-wpslug-admin.php:387 #: includes/class-wpslug-admin.php:388
msgid "Convert all slugs to lowercase for consistency" msgid "Convert all slugs to lowercase for consistency"
msgstr "将所有别名转换为小写以保持一致性" msgstr "将所有别名转换为小写以保持一致性"


@ -173,7 +152,7 @@ msgstr "将所有别名转换为小写以保持一致性"
msgid "Maximum Length" msgid "Maximum Length"
msgstr "最大长度" msgstr "最大长度"


#: includes/class-wpslug-admin.php:406 #: includes/class-wpslug-admin.php:407
msgid "Maximum length of generated slugs (0 = no limit)." msgid "Maximum length of generated slugs (0 = no limit)."
msgstr "生成的别名的最大长度0 = 无限制)。" msgstr "生成的别名的最大长度0 = 无限制)。"


@ -181,7 +160,7 @@ msgstr "生成的别名的最大长度0 = 无限制)。"
msgid "Chinese Pinyin Settings" msgid "Chinese Pinyin Settings"
msgstr "中文拼音设置" msgstr "中文拼音设置"


#: includes/class-wpslug-admin.php:422 #: includes/class-wpslug-admin.php:423
msgid "Configure Chinese characters to Pinyin romanization." msgid "Configure Chinese characters to Pinyin romanization."
msgstr "配置中文字符转换到拼音。" msgstr "配置中文字符转换到拼音。"


@ -197,7 +176,7 @@ msgstr "完整拼音ni-hao"
msgid "First Letter Only (n-h)" msgid "First Letter Only (n-h)"
msgstr "仅首字母n-h" msgstr "仅首字母n-h"


#: includes/class-wpslug-admin.php:447 #: includes/class-wpslug-admin.php:448
msgid "" msgid ""
"Choose between full pinyin or first letters only. First letter mode creates " "Choose between full pinyin or first letters only. First letter mode creates "
"very concise URLs and automatically disables SEO optimization." "very concise URLs and automatically disables SEO optimization."
@ -219,7 +198,7 @@ msgstr "下划线_"
msgid "No Separator" msgid "No Separator"
msgstr "无分隔符" msgstr "无分隔符"


#: includes/class-wpslug-admin.php:478 #: includes/class-wpslug-admin.php:479
msgid "Choose the separator between pinyin words." msgid "Choose the separator between pinyin words."
msgstr "选择拼音单词之间的分隔符。" msgstr "选择拼音单词之间的分隔符。"


@ -227,7 +206,7 @@ msgstr "选择拼音单词之间的分隔符。"
msgid "Preserve Settings" msgid "Preserve Settings"
msgstr "保留设置" msgstr "保留设置"


#: includes/class-wpslug-admin.php:497 #: includes/class-wpslug-admin.php:498
msgid "Preserve English letters in mixed content" msgid "Preserve English letters in mixed content"
msgstr "在混合内容中保留英文字母" msgstr "在混合内容中保留英文字母"


@ -235,7 +214,7 @@ msgstr "在混合内容中保留英文字母"
msgid "Preserve numbers in slugs" msgid "Preserve numbers in slugs"
msgstr "在别名中保留数字" msgstr "在别名中保留数字"


#: includes/class-wpslug-admin.php:514 #: includes/class-wpslug-admin.php:515
msgid "" msgid ""
"Keep English letters and numbers when converting mixed language content." "Keep English letters and numbers when converting mixed language content."
msgstr "转换混合语言内容时保留英文字母和数字。" msgstr "转换混合语言内容时保留英文字母和数字。"
@ -244,15 +223,15 @@ msgstr "转换混合语言内容时保留英文字母和数字。"
msgid "Transliteration Settings" msgid "Transliteration Settings"
msgstr "转写设置" msgstr "转写设置"


#: includes/class-wpslug-admin.php:530 #: includes/class-wpslug-admin.php:531
msgid "Convert foreign scripts (Cyrillic, Arabic, Greek) to Latin alphabet." msgid "Convert foreign scripts (Cyrillic, Arabic, Greek) to Latin alphabet."
msgstr "将外文字符(西里尔、阿拉伯、希腊)转换为拉丁字母。" msgstr "将外文字符(西里尔、阿拉伯、希腊)转换为拉丁字母。"


#: includes/class-wpslug-admin.php:538 #: includes/class-wpslug-admin.php:539
msgid "Transliteration Method" msgid "Transliteration Method"
msgstr "转写方法" msgstr "转写方法"


#: includes/class-wpslug-admin.php:559 #: includes/class-wpslug-admin.php:560
msgid "" msgid ""
"Choose the transliteration method. iconv and Intl provide better accuracy if " "Choose the transliteration method. iconv and Intl provide better accuracy if "
"available." "available."
@ -262,15 +241,15 @@ msgstr "选择转写方法。如果可用iconv 和 Intl 提供更好的准确
msgid "Translation Settings" msgid "Translation Settings"
msgstr "翻译设置" msgstr "翻译设置"


#: includes/class-wpslug-admin.php:575 #: includes/class-wpslug-admin.php:576
msgid "Use online translation services to convert text to English slugs." msgid "Use online translation services to convert text to English slugs."
msgstr "使用在线翻译服务将文本转换为英文别名。" msgstr "使用在线翻译服务将文本转换为英文别名。"


#: includes/class-wpslug-admin.php:583 #: includes/class-wpslug-admin.php:584
msgid "Translation Service" msgid "Translation Service"
msgstr "翻译服务" msgstr "翻译服务"


#: includes/class-wpslug-admin.php:604 #: includes/class-wpslug-admin.php:605
msgid "" msgid ""
"Choose translation service. Useful for non-English content to generate " "Choose translation service. Useful for non-English content to generate "
"English slugs." "English slugs."
@ -280,7 +259,7 @@ msgstr "选择翻译服务。对于非英文内容生成英文别名很有用。
msgid "Source Language" msgid "Source Language"
msgstr "源语言" msgstr "源语言"


#: includes/class-wpslug-admin.php:630 #: includes/class-wpslug-admin.php:631
msgid "Source language for translation. Auto-detect is recommended." msgid "Source language for translation. Auto-detect is recommended."
msgstr "翻译的源语言。推荐自动检测。" msgstr "翻译的源语言。推荐自动检测。"


@ -288,7 +267,7 @@ msgstr "翻译的源语言。推荐自动检测。"
msgid "Target Language" msgid "Target Language"
msgstr "目标语言" msgstr "目标语言"


#: includes/class-wpslug-admin.php:656 #: includes/class-wpslug-admin.php:657
msgid "Target language for translation. English is recommended for SEO." msgid "Target language for translation. English is recommended for SEO."
msgstr "翻译的目标语言。推荐英文以获得更好的SEO效果。" msgstr "翻译的目标语言。推荐英文以获得更好的SEO效果。"


@ -301,11 +280,11 @@ msgid "API Key"
msgstr "API 密钥" msgstr "API 密钥"


#: includes/class-wpslug-admin.php:679 includes/class-wpslug-admin.php:728 #: includes/class-wpslug-admin.php:679 includes/class-wpslug-admin.php:728
#: includes/class-wpslug-admin.php:1297 #: includes/class-wpslug-admin.php:1268
msgid "Test API" msgid "Test API"
msgstr "测试 API" msgstr "测试 API"


#: includes/class-wpslug-admin.php:682 #: includes/class-wpslug-admin.php:683
msgid "Enter your Google Translate API key." msgid "Enter your Google Translate API key."
msgstr "输入您的谷歌翻译 API 密钥。" msgstr "输入您的谷歌翻译 API 密钥。"


@ -321,293 +300,261 @@ msgstr "百度翻译 API"
msgid "App ID" msgid "App ID"
msgstr "应用 ID" msgstr "应用 ID"


#: includes/class-wpslug-admin.php:708 #: includes/class-wpslug-admin.php:709
msgid "Enter your Baidu Translate App ID." msgid "Enter your Baidu Translate App ID."
msgstr "输入您的百度翻译应用 ID。" msgstr "输入您的百度翻译应用 ID。"


#: includes/class-wpslug-admin.php:716 #: includes/class-wpslug-admin.php:717
msgid "Secret Key" msgid "Secret Key"
msgstr "密钥" msgstr "密钥"


#: includes/class-wpslug-admin.php:731 #: includes/class-wpslug-admin.php:732
msgid "Enter your Baidu Translate Secret Key." msgid "Enter your Baidu Translate Secret Key."
msgstr "输入您的百度翻译密钥。" msgstr "输入您的百度翻译密钥。"


#: includes/class-wpslug-admin.php:745
msgid "WPMind AI Translation"
msgstr "WPMind AI 翻译"

#: includes/class-wpslug-admin.php:750
msgid "WPMind is active and configured. No additional settings required."
msgstr "WPMind 已激活并配置完成,无需额外设置。"

#: includes/class-wpslug-admin.php:753 #: includes/class-wpslug-admin.php:753
msgid "" msgid ""
"WPMind uses AI to translate titles to SEO-friendly slugs. It provides more "
"accurate and context-aware translations compared to traditional translation "
"services."
msgstr ""

#: includes/class-wpslug-admin.php:757
msgid "Configure WPMind Settings"
msgstr "配置 WPMind 设置"

#: includes/class-wpslug-admin.php:763
msgid "WPMind plugin is not active or not configured."
msgstr "WPMind 插件未激活或未配置。"

#: includes/class-wpslug-admin.php:766
msgid ""
"Please install and activate the WPMind plugin to use AI-powered translation."
msgstr ""

#: includes/class-wpslug-admin.php:767
msgid "Learn more"
msgstr "了解更多"

#: includes/class-wpslug-admin.php:781
msgid ""
"Optimize slugs for better search engine performance and user experience." "Optimize slugs for better search engine performance and user experience."
msgstr "优化别名以获得更好的搜索引擎性能和用户体验。" msgstr "优化别名以获得更好的搜索引擎性能和用户体验。"


#: includes/class-wpslug-admin.php:789 #: includes/class-wpslug-admin.php:761
msgid "Enable SEO Optimization" msgid "Enable SEO Optimization"
msgstr "启用 SEO 优化" msgstr "启用 SEO 优化"


#: includes/class-wpslug-admin.php:804 #: includes/class-wpslug-admin.php:776
msgid "Enable SEO-friendly slug optimization" msgid "Enable SEO-friendly slug optimization"
msgstr "启用 SEO 友好的别名优化" msgstr "启用 SEO 友好的别名优化"


#: includes/class-wpslug-admin.php:810 #: includes/class-wpslug-admin.php:782
msgid "Apply SEO best practices to generated slugs." msgid "Apply SEO best practices to generated slugs."
msgstr "将 SEO 最佳实践应用于生成的别名。" msgstr "将 SEO 最佳实践应用于生成的别名。"


#: includes/class-wpslug-admin.php:818 #: includes/class-wpslug-admin.php:789
msgid "Smart Punctuation" msgid "Smart Punctuation"
msgstr "智能标点符号" msgstr "智能标点符号"


#: includes/class-wpslug-admin.php:829 #: includes/class-wpslug-admin.php:801
msgid "Intelligently handle punctuation marks" msgid "Intelligently handle punctuation marks"
msgstr "智能处理标点符号" msgstr "智能处理标点符号"


#: includes/class-wpslug-admin.php:835 #: includes/class-wpslug-admin.php:807
msgid "" msgid ""
"Convert colons, semicolons, and other punctuation to hyphens or remove them." "Convert colons, semicolons, and other punctuation to hyphens or remove them."
msgstr "将冒号、分号和其他标点符号转换为连字符或删除它们。" msgstr "将冒号、分号和其他标点符号转换为连字符或删除它们。"


#: includes/class-wpslug-admin.php:843 #: includes/class-wpslug-admin.php:815
msgid "Mixed Content Optimization" msgid "Mixed Content Optimization"
msgstr "混合内容优化" msgstr "混合内容优化"


#: includes/class-wpslug-admin.php:857 #: includes/class-wpslug-admin.php:829
msgid "Optimize mixed language and number content" msgid "Optimize mixed language and number content"
msgstr "优化混合语言和数字内容" msgstr "优化混合语言和数字内容"


#: includes/class-wpslug-admin.php:863 #: includes/class-wpslug-admin.php:835
msgid "" msgid ""
"Better handling of content mixing languages with numbers and English text." "Better handling of content mixing languages with numbers and English text."
msgstr "更好地处理语言与数字和英文文本混合的内容。" msgstr "更好地处理语言与数字和英文文本混合的内容。"


#: includes/class-wpslug-admin.php:871 #: includes/class-wpslug-admin.php:842
msgid "Remove Stop Words" msgid "Remove Stop Words"
msgstr "删除停用词" msgstr "删除停用词"


#: includes/class-wpslug-admin.php:883 #: includes/class-wpslug-admin.php:855
msgid "Remove common stop words from slugs" msgid "Remove common stop words from slugs"
msgstr "从别名中删除常见的停用词" msgstr "从别名中删除常见的停用词"


#: includes/class-wpslug-admin.php:889 #: includes/class-wpslug-admin.php:861
msgid "" msgid ""
"Remove words like \"the\", \"a\", \"an\", \"and\", etc. to create cleaner " "Remove words like \"the\", \"a\", \"an\", \"and\", etc. to create cleaner "
"slugs." "slugs."
msgstr "删除像\"the\"、\"a\"、\"an\"、\"and\"等词语以创建更清洁的别名。" msgstr "删除像\"the\"、\"a\"、\"an\"、\"and\"等词语以创建更清洁的别名。"


#: includes/class-wpslug-admin.php:897 #: includes/class-wpslug-admin.php:868
msgid "Maximum Words" msgid "Maximum Words"
msgstr "最大单词数" msgstr "最大单词数"


#: includes/class-wpslug-admin.php:908 #: includes/class-wpslug-admin.php:880
msgid "Maximum number of words to keep in slug for SEO optimization." msgid "Maximum number of words to keep in slug for SEO optimization."
msgstr "为 SEO 优化在别名中保留的最大单词数。" msgstr "为 SEO 优化在别名中保留的最大单词数。"


#: includes/class-wpslug-admin.php:916 #: includes/class-wpslug-admin.php:887
msgid "Stop Words List" msgid "Stop Words List"
msgstr "停用词列表" msgstr "停用词列表"


#: includes/class-wpslug-admin.php:926 #: includes/class-wpslug-admin.php:898
msgid "Comma-separated list of stop words to remove from slugs." msgid "Comma-separated list of stop words to remove from slugs."
msgstr "从别名中删除的停用词的逗号分隔列表。" msgstr "从别名中删除的停用词的逗号分隔列表。"


#: includes/class-wpslug-admin.php:942 #: includes/class-wpslug-admin.php:914
msgid "Configure how media file names are handled during upload." msgid "Configure how media file names are handled during upload."
msgstr "配置上传期间如何处理媒体文件名。" msgstr "配置上传期间如何处理媒体文件名。"


#: includes/class-wpslug-admin.php:950 #: includes/class-wpslug-admin.php:922
msgid "Media File Conversion" msgid "Media File Conversion"
msgstr "媒体文件转换" msgstr "媒体文件转换"


#: includes/class-wpslug-admin.php:964 #: includes/class-wpslug-admin.php:936
msgid "Disable automatic file name conversion for uploaded media" msgid "Disable automatic file name conversion for uploaded media"
msgstr "禁用上传媒体的自动文件名转换" msgstr "禁用上传媒体的自动文件名转换"


#: includes/class-wpslug-admin.php:970 #: includes/class-wpslug-admin.php:942
msgid "When checked, media files will not be converted automatically." msgid "When checked, media files will not be converted automatically."
msgstr "选中时,媒体文件不会自动转换。" msgstr "选中时,媒体文件不会自动转换。"


#: includes/class-wpslug-admin.php:978 #: includes/class-wpslug-admin.php:950
msgid "Media Conversion Mode" msgid "Media Conversion Mode"
msgstr "媒体转换模式" msgstr "媒体转换模式"


#: includes/class-wpslug-admin.php:988 includes/class-wpslug-settings.php:578 #: includes/class-wpslug-admin.php:960 includes/class-wpslug-settings.php:544
msgid "Normal Conversion (same as content)" msgid "Normal Conversion (same as content)"
msgstr "普通转换(与内容相同)" msgstr "普通转换(与内容相同)"


#: includes/class-wpslug-admin.php:997 includes/class-wpslug-settings.php:579 #: includes/class-wpslug-admin.php:969 includes/class-wpslug-settings.php:545
msgid "MD5 Hash (generates unique hash)" msgid "MD5 Hash (generates unique hash)"
msgstr "MD5 哈希(生成唯一哈希)" msgstr "MD5 哈希(生成唯一哈希)"


#: includes/class-wpslug-admin.php:1006 includes/class-wpslug-settings.php:580 #: includes/class-wpslug-admin.php:978 includes/class-wpslug-settings.php:546
msgid "No Conversion (keep original)" msgid "No Conversion (keep original)"
msgstr "不转换(保持原样)" msgstr "不转换(保持原样)"


#: includes/class-wpslug-admin.php:1013 #: includes/class-wpslug-admin.php:985
msgid "" msgid ""
"Choose how media file names should be processed. MD5 creates unique hashes " "Choose how media file names should be processed. MD5 creates unique hashes "
"for file names." "for file names."
msgstr "选择如何处理媒体文件名。MD5 为文件名创建唯一哈希。" msgstr "选择如何处理媒体文件名。MD5 为文件名创建唯一哈希。"


#: includes/class-wpslug-admin.php:1021 #: includes/class-wpslug-admin.php:992
msgid "Media File Prefix" msgid "Media File Prefix"
msgstr "媒体文件前缀" msgstr "媒体文件前缀"


#: includes/class-wpslug-admin.php:1030 #: includes/class-wpslug-admin.php:1002
msgid "" msgid ""
"Optional prefix to add to all media file names (e.g., \"img-\", \"file-\")." "Optional prefix to add to all media file names (e.g., \"img-\", \"file-\")."
msgstr "可选前缀添加到所有媒体文件名(例如:\"img-\"、\"file-\")。" msgstr "可选前缀添加到所有媒体文件名(例如:\"img-\"、\"file-\")。"


#: includes/class-wpslug-admin.php:1038 #: includes/class-wpslug-admin.php:1010
msgid "Preserve Original Extension" msgid "Preserve Original Extension"
msgstr "保留原始扩展名" msgstr "保留原始扩展名"


#: includes/class-wpslug-admin.php:1052 #: includes/class-wpslug-admin.php:1024
msgid "Always preserve the original file extension" msgid "Always preserve the original file extension"
msgstr "始终保留原始文件扩展名" msgstr "始终保留原始文件扩展名"


#: includes/class-wpslug-admin.php:1058 #: includes/class-wpslug-admin.php:1030
msgid "Ensures file extensions are kept even when using MD5 conversion." msgid "Ensures file extensions are kept even when using MD5 conversion."
msgstr "确保即使使用 MD5 转换也保留文件扩展名。" msgstr "确保即使使用 MD5 转换也保留文件扩展名。"


#: includes/class-wpslug-admin.php:1073 #: includes/class-wpslug-admin.php:1044
msgid "Advanced Settings" msgid "Advanced Settings"
msgstr "高级设置" msgstr "高级设置"


#: includes/class-wpslug-admin.php:1074 #: includes/class-wpslug-admin.php:1046
msgid "Advanced options and content type configuration for power users." msgid "Advanced options and content type configuration for power users."
msgstr "为高级用户提供的高级选项和内容类型配置。" msgstr "为高级用户提供的高级选项和内容类型配置。"


#: includes/class-wpslug-admin.php:1082 #: includes/class-wpslug-admin.php:1053
msgid "Content Types" msgid "Content Types"
msgstr "内容类型" msgstr "内容类型"


#: includes/class-wpslug-admin.php:1084 #: includes/class-wpslug-admin.php:1055
msgid "Post Types" msgid "Post Types"
msgstr "文章类型" msgstr "文章类型"


#: includes/class-wpslug-admin.php:1116 #: includes/class-wpslug-admin.php:1088
msgid "Select post types to apply slug conversion." msgid "Select post types to apply slug conversion."
msgstr "选择要应用别名转换的文章类型。" msgstr "选择要应用别名转换的文章类型。"


#: includes/class-wpslug-admin.php:1122 #: includes/class-wpslug-admin.php:1093
msgid "Taxonomies" msgid "Taxonomies"
msgstr "分类法" msgstr "分类法"


#: includes/class-wpslug-admin.php:1154 #: includes/class-wpslug-admin.php:1126
msgid "Select taxonomies to apply slug conversion." msgid "Select taxonomies to apply slug conversion."
msgstr "选择要应用别名转换的分类法。" msgstr "选择要应用别名转换的分类法。"


#: includes/class-wpslug-admin.php:1162 #: includes/class-wpslug-admin.php:1133
msgid "Display Options" msgid "Display Options"
msgstr "显示选项" msgstr "显示选项"


#: includes/class-wpslug-admin.php:1173 #: includes/class-wpslug-admin.php:1145
msgid "Show slug column in post and page lists for easy reference" msgid "Show slug column in post and page lists for easy reference"
msgstr "在文章和页面列表中显示别名列以便于参考" msgstr "在文章和页面列表中显示别名列以便于参考"


#: includes/class-wpslug-admin.php:1203 #: includes/class-wpslug-admin.php:1175
msgid "WP Slug Plugin Active" msgid "WP Slug Plugin Active"
msgstr "文派素格WP Slug )插件已激活" msgstr "文派素格WP Slug )插件已激活"


#: includes/class-wpslug-admin.php:1207 #: includes/class-wpslug-admin.php:1179
msgid "Your slugs are automatically converted based on your WP Slug settings." msgid "Your slugs are automatically converted based on your WP Slug settings."
msgstr "您的别名根据您的 文派素格WP Slug )设置自动转换。" msgstr "您的别名根据您的 文派素格WP Slug )设置自动转换。"


#: includes/class-wpslug-admin.php:1214 #: includes/class-wpslug-admin.php:1185
msgid "Configure WP Slug" msgid "Configure WP Slug"
msgstr "配置 WP Slug" msgstr "配置 WP Slug"


#: includes/class-wpslug-admin.php:1295 #: includes/class-wpslug-admin.php:1266
msgid "Converting..." msgid "Converting..."
msgstr "转换中..." msgstr "转换中..."


#: includes/class-wpslug-admin.php:1296 #: includes/class-wpslug-admin.php:1267
msgid "Testing..." msgid "Testing..."
msgstr "测试中..." msgstr "测试中..."


#: includes/class-wpslug-admin.php:1298 #: includes/class-wpslug-admin.php:1270
msgid "Are you sure you want to reset all settings to default values?" msgid "Are you sure you want to reset all settings to default values?"
msgstr "您确定要将所有设置重置为默认值吗?" msgstr "您确定要将所有设置重置为默认值吗?"


#: includes/class-wpslug-admin.php:1302 includes/class-wpslug-admin.php:1402 #: includes/class-wpslug-admin.php:1274 includes/class-wpslug-admin.php:1373
msgid "API connection successful!" msgid "API connection successful!"
msgstr "API 连接成功!" msgstr "API 连接成功!"


#: includes/class-wpslug-admin.php:1306 includes/class-wpslug-admin.php:1406 #: includes/class-wpslug-admin.php:1278 includes/class-wpslug-admin.php:1378
msgid "API connection failed. Please check your credentials." msgid "API connection failed. Please check your credentials."
msgstr "API 连接失败。请检查您的凭证。" msgstr "API 连接失败。请检查您的凭证。"


#: includes/class-wpslug-admin.php:1310 includes/class-wpslug-admin.php:1328 #: includes/class-wpslug-admin.php:1281 includes/class-wpslug-admin.php:1299
msgid "Please enter some text to preview." msgid "Please enter some text to preview."
msgstr "请输入一些文本以预览。" msgstr "请输入一些文本以预览。"


#: includes/class-wpslug-admin.php:1311 includes/class-wpslug-admin.php:1346 #: includes/class-wpslug-admin.php:1283 includes/class-wpslug-admin.php:1318
msgid "Conversion failed. Please check your settings." msgid "Conversion failed. Please check your settings."
msgstr "转换失败。请检查您的设置。" msgstr "转换失败。请检查您的设置。"


#: includes/class-wpslug-admin.php:1365 #: includes/class-wpslug-admin.php:1337
msgid "Google API key is required for testing." msgid "Google API key is required for testing."
msgstr "测试需要谷歌 API 密钥。" msgstr "测试需要谷歌 API 密钥。"


#: includes/class-wpslug-admin.php:1377 #: includes/class-wpslug-admin.php:1349
msgid "Both Baidu App ID and Secret Key are required for testing." msgid "Both Baidu App ID and Secret Key are required for testing."
msgstr "测试需要百度应用 ID 和密钥。" msgstr "测试需要百度应用 ID 和密钥。"


#: includes/class-wpslug-admin.php:1386 #: includes/class-wpslug-admin.php:1357
msgid "Invalid service selected." msgid "Invalid service selected."
msgstr "选择了无效的服务。" msgstr "选择了无效的服务。"


#: includes/class-wpslug-admin.php:1415 #: includes/class-wpslug-admin.php:1386
msgid "API connection failed: " msgid "API connection failed: "
msgstr "API 连接失败:" msgstr "API 连接失败:"


#: includes/class-wpslug-admin.php:1440 #: includes/class-wpslug-admin.php:1412
msgid "Disable automatic slug conversion for this post" msgid "Disable automatic slug conversion for this post"
msgstr "禁用此文章的自动别名转换" msgstr "禁用此文章的自动别名转换"


#: includes/class-wpslug-admin.php:1457 #: includes/class-wpslug-admin.php:1428
#, php-format #, php-format
msgid "Convert Slugs (%s)" msgid "Convert Slugs (%s)"
msgstr "转换别名(%s" msgstr "转换别名(%s"


#: includes/class-wpslug-admin.php:1511 #: includes/class-wpslug-admin.php:1482
#, php-format #, php-format
msgid "Successfully converted %d slug(s)." msgid "Successfully converted %d slug(s)."
msgstr "成功转换了 %d 个别名。" msgstr "成功转换了 %d 个别名。"


#: includes/class-wpslug-core.php:363 #: includes/class-wpslug-core.php:327
msgid "N/A" msgid "N/A"
msgstr "不适用" msgstr "不适用"


#: includes/class-wpslug-core.php:378 #: includes/class-wpslug-core.php:342
msgid "Error" msgid "Error"
msgstr "错误" msgstr "错误"


@ -615,237 +562,213 @@ msgstr "错误"
msgid "Chinese Pinyin Conversion" msgid "Chinese Pinyin Conversion"
msgstr "中文拼音转换" msgstr "中文拼音转换"


#: includes/class-wpslug-settings.php:246 #: includes/class-wpslug-settings.php:243
msgid "Semantic Pinyin (WPMind AI)"
msgstr "语义化拼音WPMind AI"

#: includes/class-wpslug-settings.php:248
msgid "Semantic Pinyin (Requires WPMind)"
msgstr "语义化拼音(需要 WPMind"

#: includes/class-wpslug-settings.php:251
msgid "Foreign Language Transliteration" msgid "Foreign Language Transliteration"
msgstr "外语音译" msgstr "外语音译"


#: includes/class-wpslug-settings.php:255 #: includes/class-wpslug-settings.php:246
msgid "Multi-language Translation" msgid "Multi-language Translation"
msgstr "多语言翻译" msgstr "多语言翻译"


#: includes/class-wpslug-settings.php:263 #: includes/class-wpslug-settings.php:253
msgid "Basic Character Mapping" msgid "Basic Character Mapping"
msgstr "基本字符映射" msgstr "基本字符映射"


#: includes/class-wpslug-settings.php:267 #: includes/class-wpslug-settings.php:257
msgid "iconv Transliteration" msgid "iconv Transliteration"
msgstr "iconv 音译" msgstr "iconv 音译"


#: includes/class-wpslug-settings.php:271 #: includes/class-wpslug-settings.php:261
msgid "PHP Intl Extension" msgid "PHP Intl Extension"
msgstr "PHP Intl 扩展" msgstr "PHP Intl 扩展"


#: includes/class-wpslug-settings.php:280 #: includes/class-wpslug-settings.php:270
msgid "None" msgid "None"
msgstr "无" msgstr "无"


#: includes/class-wpslug-settings.php:281 #: includes/class-wpslug-settings.php:271
msgid "Google Translate" msgid "Google Translate"
msgstr "谷歌翻译" msgstr "谷歌翻译"


#: includes/class-wpslug-settings.php:282 #: includes/class-wpslug-settings.php:272
msgid "Baidu Translate" msgid "Baidu Translate"
msgstr "百度翻译" msgstr "百度翻译"


#: includes/class-wpslug-settings.php:289 #: includes/class-wpslug-settings.php:279
msgid "WPMind AI (Recommended)"
msgstr "WPMind AI推荐"

#: includes/class-wpslug-settings.php:294
msgid "WPMind AI (Not Configured)"
msgstr "WPMind AI未配置"

#: includes/class-wpslug-settings.php:303
msgid "Auto Detect" msgid "Auto Detect"
msgstr "自动检测" msgstr "自动检测"


#: includes/class-wpslug-settings.php:304 #: includes/class-wpslug-settings.php:280
msgid "Chinese (Simplified)" msgid "Chinese (Simplified)"
msgstr "中文(简体)" msgstr "中文(简体)"


#: includes/class-wpslug-settings.php:305 #: includes/class-wpslug-settings.php:281
msgid "Chinese (Traditional)" msgid "Chinese (Traditional)"
msgstr "中文(繁体)" msgstr "中文(繁体)"


#: includes/class-wpslug-settings.php:306 #: includes/class-wpslug-settings.php:282
msgid "English" msgid "English"
msgstr "英语" msgstr "英语"


#: includes/class-wpslug-settings.php:307 #: includes/class-wpslug-settings.php:283
msgid "Spanish" msgid "Spanish"
msgstr "西班牙语" msgstr "西班牙语"


#: includes/class-wpslug-settings.php:308 #: includes/class-wpslug-settings.php:284
msgid "French" msgid "French"
msgstr "法语" msgstr "法语"


#: includes/class-wpslug-settings.php:309 #: includes/class-wpslug-settings.php:285
msgid "German" msgid "German"
msgstr "德语" msgstr "德语"


#: includes/class-wpslug-settings.php:310 #: includes/class-wpslug-settings.php:286
msgid "Japanese" msgid "Japanese"
msgstr "日语" msgstr "日语"


#: includes/class-wpslug-settings.php:311 #: includes/class-wpslug-settings.php:287
msgid "Korean" msgid "Korean"
msgstr "韩语" msgstr "韩语"


#: includes/class-wpslug-settings.php:312 #: includes/class-wpslug-settings.php:288
msgid "Russian" msgid "Russian"
msgstr "俄语" msgstr "俄语"


#: includes/class-wpslug-settings.php:313 #: includes/class-wpslug-settings.php:289
msgid "Arabic" msgid "Arabic"
msgstr "阿拉伯语" msgstr "阿拉伯语"


#: includes/class-wpslug-settings.php:314 #: includes/class-wpslug-settings.php:290
msgid "Italian" msgid "Italian"
msgstr "意大利语" msgstr "意大利语"


#: includes/class-wpslug-settings.php:315 #: includes/class-wpslug-settings.php:291
msgid "Portuguese" msgid "Portuguese"
msgstr "葡萄牙语" msgstr "葡萄牙语"


#: includes/class-wpslug-settings.php:316 #: includes/class-wpslug-settings.php:292
msgid "Dutch" msgid "Dutch"
msgstr "荷兰语" msgstr "荷兰语"


#: includes/class-wpslug-settings.php:317 #: includes/class-wpslug-settings.php:293
msgid "Polish" msgid "Polish"
msgstr "波兰语" msgstr "波兰语"


#: includes/class-wpslug-settings.php:318 #: includes/class-wpslug-settings.php:294
msgid "Turkish" msgid "Turkish"
msgstr "土耳其语" msgstr "土耳其语"


#: includes/class-wpslug-settings.php:319 #: includes/class-wpslug-settings.php:295
msgid "Swedish" msgid "Swedish"
msgstr "瑞典语" msgstr "瑞典语"


#: includes/class-wpslug-settings.php:320 #: includes/class-wpslug-settings.php:296
msgid "Danish" msgid "Danish"
msgstr "丹麦语" msgstr "丹麦语"


#: includes/class-wpslug-settings.php:321 #: includes/class-wpslug-settings.php:297
msgid "Norwegian" msgid "Norwegian"
msgstr "挪威语" msgstr "挪威语"


#: includes/class-wpslug-settings.php:322 #: includes/class-wpslug-settings.php:298
msgid "Finnish" msgid "Finnish"
msgstr "芬兰语" msgstr "芬兰语"


#: includes/class-wpslug-settings.php:323 #: includes/class-wpslug-settings.php:299
msgid "Czech" msgid "Czech"
msgstr "捷克语" msgstr "捷克语"


#: includes/class-wpslug-settings.php:324 #: includes/class-wpslug-settings.php:300
msgid "Hungarian" msgid "Hungarian"
msgstr "匈牙利语" msgstr "匈牙利语"


#: includes/class-wpslug-settings.php:325 #: includes/class-wpslug-settings.php:301
msgid "Romanian" msgid "Romanian"
msgstr "罗马尼亚语" msgstr "罗马尼亚语"


#: includes/class-wpslug-settings.php:326 #: includes/class-wpslug-settings.php:302
msgid "Bulgarian" msgid "Bulgarian"
msgstr "保加利亚语" msgstr "保加利亚语"


#: includes/class-wpslug-settings.php:327 #: includes/class-wpslug-settings.php:303
msgid "Croatian" msgid "Croatian"
msgstr "克罗地亚语" msgstr "克罗地亚语"


#: includes/class-wpslug-settings.php:328 #: includes/class-wpslug-settings.php:304
msgid "Slovak" msgid "Slovak"
msgstr "斯洛伐克语" msgstr "斯洛伐克语"


#: includes/class-wpslug-settings.php:329 #: includes/class-wpslug-settings.php:305
msgid "Slovenian" msgid "Slovenian"
msgstr "斯洛文尼亚语" msgstr "斯洛文尼亚语"


#: includes/class-wpslug-settings.php:330 #: includes/class-wpslug-settings.php:306
msgid "Estonian" msgid "Estonian"
msgstr "爱沙尼亚语" msgstr "爱沙尼亚语"


#: includes/class-wpslug-settings.php:331 #: includes/class-wpslug-settings.php:307
msgid "Latvian" msgid "Latvian"
msgstr "拉脱维亚语" msgstr "拉脱维亚语"


#: includes/class-wpslug-settings.php:332 #: includes/class-wpslug-settings.php:308
msgid "Lithuanian" msgid "Lithuanian"
msgstr "立陶宛语" msgstr "立陶宛语"


#: includes/class-wpslug-settings.php:333 #: includes/class-wpslug-settings.php:309
msgid "Maltese" msgid "Maltese"
msgstr "马耳他语" msgstr "马耳他语"


#: includes/class-wpslug-settings.php:334 #: includes/class-wpslug-settings.php:310
msgid "Greek" msgid "Greek"
msgstr "希腊语" msgstr "希腊语"


#: includes/class-wpslug-settings.php:335 #: includes/class-wpslug-settings.php:311
msgid "Welsh" msgid "Welsh"
msgstr "威尔士语" msgstr "威尔士语"


#: includes/class-wpslug-settings.php:421 #: includes/class-wpslug-settings.php:387
msgid "Invalid import data format." msgid "Invalid import data format."
msgstr "无效的导入数据格式。" msgstr "无效的导入数据格式。"


#: includes/class-wpslug-settings.php:434 #: includes/class-wpslug-settings.php:400
msgid "Failed to update options." msgid "Failed to update options."
msgstr "更新选项失败。" msgstr "更新选项失败。"


#: includes/class-wpslug-settings.php:702 #: includes/class-wpslug-settings.php:669
#: includes/class-wpslug-validator.php:155 #: includes/class-wpslug-validator.php:154
msgid "Google API key is required for Google Translate service." msgid "Google API key is required for Google Translate service."
msgstr "谷歌翻译服务需要谷歌 API 密钥。" msgstr "谷歌翻译服务需要谷歌 API 密钥。"


#: includes/class-wpslug-settings.php:712 #: includes/class-wpslug-settings.php:679
#: includes/class-wpslug-validator.php:159 #: includes/class-wpslug-validator.php:158
msgid "Baidu App ID and Secret Key are required for Baidu Translate service." msgid "Baidu App ID and Secret Key are required for Baidu Translate service."
msgstr "百度翻译服务需要百度应用 ID 和密钥。" msgstr "百度翻译服务需要百度应用 ID 和密钥。"


#: includes/class-wpslug-settings.php:721 #: includes/class-wpslug-settings.php:687
#: includes/class-wpslug-validator.php:186 #: includes/class-wpslug-validator.php:176
msgid "PHP 7.0 or higher is required." msgid "PHP 7.0 or higher is required."
msgstr "需要 PHP 7.0 或更高版本。" msgstr "需要 PHP 7.0 或更高版本。"


#: includes/class-wpslug-settings.php:724 #: includes/class-wpslug-settings.php:691
#: includes/class-wpslug-validator.php:190 #: includes/class-wpslug-validator.php:180
msgid "WordPress 5.0 or higher is required." msgid "WordPress 5.0 or higher is required."
msgstr "需要 WordPress 5.0 或更高版本。" msgstr "需要 WordPress 5.0 或更高版本。"


#: includes/class-wpslug-settings.php:730 #: includes/class-wpslug-settings.php:696
#: includes/class-wpslug-validator.php:194 #: includes/class-wpslug-validator.php:184
msgid "PHP mbstring extension is required." msgid "PHP mbstring extension is required."
msgstr "需要 PHP mbstring 扩展。" msgstr "需要 PHP mbstring 扩展。"


#: includes/class-wpslug-settings.php:733 #: includes/class-wpslug-settings.php:699
#: includes/class-wpslug-validator.php:198 #: includes/class-wpslug-validator.php:188
msgid "PHP JSON extension is required." msgid "PHP JSON extension is required."
msgstr "需要 PHP JSON 扩展。" msgstr "需要 PHP JSON 扩展。"


#: includes/class-wpslug-validator.php:165 #: wpslug.php:63
msgid "WPMind plugin is not installed."
msgstr "WPMind 插件未安装。"

#: includes/class-wpslug-validator.php:167
msgid "WPMind is not configured. Please configure it in WPMind settings."
msgstr "WPMind 未配置。请在 WPMind 设置中进行配置。"

#: wpslug.php:67
msgid "WP Slug requires PHP 7.0 or higher. Please upgrade your PHP version." msgid "WP Slug requires PHP 7.0 or higher. Please upgrade your PHP version."
msgstr "文派素格WP Slug )需要 PHP 7.0 或更高版本。请升级您的 PHP 版本。" msgstr "文派素格WP Slug )需要 PHP 7.0 或更高版本。请升级您的 PHP 版本。"


#: wpslug.php:76 #: wpslug.php:72
msgid "" msgid ""
"WP Slug requires WordPress 5.0 or higher. Please upgrade your WordPress " "WP Slug requires WordPress 5.0 or higher. Please upgrade your WordPress "
"version." "version."
@ -853,20 +776,36 @@ msgstr ""
"文派素格WP Slug )需要 WordPress 5.0 或更高版本。请升级您的 WordPress 版" "文派素格WP Slug )需要 WordPress 5.0 或更高版本。请升级您的 WordPress 版"
"本。" "本。"


#: wpslug.php:130 #: wpslug.php:125
msgid "" msgid ""
"WP Slug plugin requirements not met. Please check your PHP and WordPress " "WP Slug plugin requirements not met. Please check your PHP and WordPress "
"versions." "versions."
msgstr "文派素格WP Slug )插件要求未满足。请检查您的 PHP 和 WordPress 版本。" msgstr "文派素格WP Slug )插件要求未满足。请检查您的 PHP 和 WordPress 版本。"


#: wpslug.php:131 wpslug.php:151 #: wpslug.php:126 wpslug.php:146
msgid "Plugin Activation Error" msgid "Plugin Activation Error"
msgstr "插件激活错误" msgstr "插件激活错误"


#: wpslug.php:150 #: wpslug.php:145
msgid "" msgid ""
"An error occurred during plugin activation. Please check your server logs." "An error occurred during plugin activation. Please check your server logs."
msgstr "插件激活期间发生错误。请检查您的服务器日志。" msgstr "插件激活期间发生错误。请检查您的服务器日志。"


#~ msgid "WPSlug.com" #. Plugin Name of the plugin/theme
#~ msgstr "文派素格" msgid "WPSlug"
msgstr "文派素格"

#. Plugin URI of the plugin/theme
#. Author URI of the plugin/theme
msgid "https://wpslug.com"
msgstr "https://wpslug.com"

#. Description of the plugin/theme
msgid ""
"Advanced slug management plugin with Chinese Pinyin support and SEO "
"optimization."
msgstr "具有中文拼音支持和 SEO 优化的高级别名管理插件。"

#. Author of the plugin/theme
msgid "WPSlug.com"
msgstr "文派素格"

View file

@ -1,42 +1,30 @@
# Copyright (C) 2026 WPSlug #, fuzzy
# This file is distributed under the GPL2.
msgid "" msgid ""
msgstr "" msgstr ""
"Project-Id-Version: WPSlug 1.1.0\n" "Project-Id-Version: WPSlug\n"
"Report-Msgid-Bugs-To: https://wordpress.org/support/plugin/wpslug\n" "POT-Creation-Date: 2025-07-13 19:54+0800\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n" "PO-Revision-Date: 2025-07-13 19:54+0800\n"
"Language-Team: LANGUAGE <LL@li.org>\n" "Last-Translator: \n"
"Language-Team: \n"
"MIME-Version: 1.0\n" "MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n" "Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n" "Content-Transfer-Encoding: 8bit\n"
"POT-Creation-Date: 2026-02-28T15:19:21+08:00\n" "Plural-Forms: nplurals=INTEGER; plural=EXPRESSION;\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "X-Generator: Poedit 3.6\n"
"X-Generator: WP-CLI 2.12.0\n" "X-Poedit-Basepath: ..\n"
"X-Domain: wpslug\n" "X-Poedit-Flags-xgettext: --add-comments=translators:\n"

"X-Poedit-WPHeader: wpslug.php\n"
#. Plugin Name of the plugin "X-Poedit-SourceCharset: UTF-8\n"
#. Author of the plugin "X-Poedit-KeywordsList: "
#: wpslug.php "__;_e;_n:1,2;_x:1,2c;_ex:1,2c;_nx:4c,1,2;esc_attr__;esc_attr_e;esc_attr_x:1,2c;esc_html__;esc_html_e;esc_html_x:1,2c;_n_noop:1,2;_nx_noop:3c,1,2;__ngettext_noop:1,2\n"
msgid "WPSlug" "X-Poedit-SearchPath-0: .\n"
msgstr "" "X-Poedit-SearchPathExcluded-0: *.min.js\n"

#. Plugin URI of the plugin
#. Author URI of the plugin
#: wpslug.php
msgid "https://wpcy.com/slug"
msgstr ""

#. Description of the plugin
#: wpslug.php
msgid "Advanced slug management plugin with Chinese Pinyin support and SEO optimization."
msgstr ""


#: includes/class-wpslug-admin.php:56 #: includes/class-wpslug-admin.php:56
msgid "WPSlug Settings" msgid "WPSlug Settings"
msgstr "" msgstr ""


#: includes/class-wpslug-admin.php:57 #: includes/class-wpslug-admin.php:57 includes/class-wpslug-core.php:310
#: includes/class-wpslug-core.php:346
msgid "Slug" msgid "Slug"
msgstr "" msgstr ""


@ -44,7 +32,7 @@ msgstr ""
msgid "Settings saved successfully!" msgid "Settings saved successfully!"
msgstr "" msgstr ""


#: includes/class-wpslug-admin.php:112 #: includes/class-wpslug-admin.php:113
msgid "You do not have sufficient permissions to access this page." msgid "You do not have sufficient permissions to access this page."
msgstr "" msgstr ""


@ -81,13 +69,11 @@ msgstr ""
msgid "Translation" msgid "Translation"
msgstr "" msgstr ""


#: includes/class-wpslug-admin.php:188 #: includes/class-wpslug-admin.php:188 includes/class-wpslug-admin.php:751
#: includes/class-wpslug-admin.php:780
msgid "SEO Optimization" msgid "SEO Optimization"
msgstr "" msgstr ""


#: includes/class-wpslug-admin.php:194 #: includes/class-wpslug-admin.php:194 includes/class-wpslug-admin.php:912
#: includes/class-wpslug-admin.php:941
msgid "Media Files" msgid "Media Files"
msgstr "" msgstr ""


@ -107,17 +93,16 @@ msgstr ""
msgid "Debug Checkboxes" msgid "Debug Checkboxes"
msgstr "" msgstr ""


#: includes/class-wpslug-admin.php:277 #: includes/class-wpslug-admin.php:277 includes/class-wpslug-admin.php:290
#: includes/class-wpslug-admin.php:290 #: includes/class-wpslug-admin.php:1265
#: includes/class-wpslug-admin.php:1294
msgid "Preview" msgid "Preview"
msgstr "" msgstr ""


#: includes/class-wpslug-admin.php:279 #: includes/class-wpslug-admin.php:280
msgid "Test your conversion settings with live preview." msgid "Test your conversion settings with live preview."
msgstr "" msgstr ""


#: includes/class-wpslug-admin.php:285 #: includes/class-wpslug-admin.php:286
msgid "Enter text to preview conversion..." msgid "Enter text to preview conversion..."
msgstr "" msgstr ""


@ -125,7 +110,7 @@ msgstr ""
msgid "General Settings" msgid "General Settings"
msgstr "" msgstr ""


#: includes/class-wpslug-admin.php:306 #: includes/class-wpslug-admin.php:307
msgid "Configure basic plugin behavior and choose your conversion method." msgid "Configure basic plugin behavior and choose your conversion method."
msgstr "" msgstr ""


@ -133,7 +118,7 @@ msgstr ""
msgid "Enable Plugin" msgid "Enable Plugin"
msgstr "" msgstr ""


#: includes/class-wpslug-admin.php:326 #: includes/class-wpslug-admin.php:327
msgid "Enable automatic slug conversion for your content" msgid "Enable automatic slug conversion for your content"
msgstr "" msgstr ""


@ -141,15 +126,17 @@ msgstr ""
msgid "Conversion Mode" msgid "Conversion Mode"
msgstr "" msgstr ""


#: includes/class-wpslug-admin.php:352 #: includes/class-wpslug-admin.php:353
msgid "Select the conversion method. Pinyin for Chinese, Transliteration for Cyrillic/Arabic scripts, Translation for other languages." msgid ""
"Select the conversion method. Pinyin for Chinese, Transliteration for "
"Cyrillic/Arabic scripts, Translation for other languages."
msgstr "" msgstr ""


#: includes/class-wpslug-admin.php:360 #: includes/class-wpslug-admin.php:360
msgid "Auto Convert" msgid "Auto Convert"
msgstr "" msgstr ""


#: includes/class-wpslug-admin.php:368 #: includes/class-wpslug-admin.php:369
msgid "Automatically convert slugs when saving posts and terms" msgid "Automatically convert slugs when saving posts and terms"
msgstr "" msgstr ""


@ -157,7 +144,7 @@ msgstr ""
msgid "Force Lowercase" msgid "Force Lowercase"
msgstr "" msgstr ""


#: includes/class-wpslug-admin.php:387 #: includes/class-wpslug-admin.php:388
msgid "Convert all slugs to lowercase for consistency" msgid "Convert all slugs to lowercase for consistency"
msgstr "" msgstr ""


@ -165,7 +152,7 @@ msgstr ""
msgid "Maximum Length" msgid "Maximum Length"
msgstr "" msgstr ""


#: includes/class-wpslug-admin.php:406 #: includes/class-wpslug-admin.php:407
msgid "Maximum length of generated slugs (0 = no limit)." msgid "Maximum length of generated slugs (0 = no limit)."
msgstr "" msgstr ""


@ -173,7 +160,7 @@ msgstr ""
msgid "Chinese Pinyin Settings" msgid "Chinese Pinyin Settings"
msgstr "" msgstr ""


#: includes/class-wpslug-admin.php:422 #: includes/class-wpslug-admin.php:423
msgid "Configure Chinese characters to Pinyin romanization." msgid "Configure Chinese characters to Pinyin romanization."
msgstr "" msgstr ""


@ -189,8 +176,10 @@ msgstr ""
msgid "First Letter Only (n-h)" msgid "First Letter Only (n-h)"
msgstr "" msgstr ""


#: includes/class-wpslug-admin.php:447 #: includes/class-wpslug-admin.php:448
msgid "Choose between full pinyin or first letters only. First letter mode creates very concise URLs and automatically disables SEO optimization." msgid ""
"Choose between full pinyin or first letters only. First letter mode creates "
"very concise URLs and automatically disables SEO optimization."
msgstr "" msgstr ""


#: includes/class-wpslug-admin.php:455 #: includes/class-wpslug-admin.php:455
@ -209,7 +198,7 @@ msgstr ""
msgid "No Separator" msgid "No Separator"
msgstr "" msgstr ""


#: includes/class-wpslug-admin.php:478 #: includes/class-wpslug-admin.php:479
msgid "Choose the separator between pinyin words." msgid "Choose the separator between pinyin words."
msgstr "" msgstr ""


@ -217,7 +206,7 @@ msgstr ""
msgid "Preserve Settings" msgid "Preserve Settings"
msgstr "" msgstr ""


#: includes/class-wpslug-admin.php:497 #: includes/class-wpslug-admin.php:498
msgid "Preserve English letters in mixed content" msgid "Preserve English letters in mixed content"
msgstr "" msgstr ""


@ -225,47 +214,52 @@ msgstr ""
msgid "Preserve numbers in slugs" msgid "Preserve numbers in slugs"
msgstr "" msgstr ""


#: includes/class-wpslug-admin.php:514 #: includes/class-wpslug-admin.php:515
msgid "Keep English letters and numbers when converting mixed language content." msgid ""
"Keep English letters and numbers when converting mixed language content."
msgstr "" msgstr ""


#: includes/class-wpslug-admin.php:529 #: includes/class-wpslug-admin.php:529
msgid "Transliteration Settings" msgid "Transliteration Settings"
msgstr "" msgstr ""


#: includes/class-wpslug-admin.php:530 #: includes/class-wpslug-admin.php:531
msgid "Convert foreign scripts (Cyrillic, Arabic, Greek) to Latin alphabet." msgid "Convert foreign scripts (Cyrillic, Arabic, Greek) to Latin alphabet."
msgstr "" msgstr ""


#: includes/class-wpslug-admin.php:538 #: includes/class-wpslug-admin.php:539
msgid "Transliteration Method" msgid "Transliteration Method"
msgstr "" msgstr ""


#: includes/class-wpslug-admin.php:559 #: includes/class-wpslug-admin.php:560
msgid "Choose the transliteration method. iconv and Intl provide better accuracy if available." msgid ""
"Choose the transliteration method. iconv and Intl provide better accuracy if "
"available."
msgstr "" msgstr ""


#: includes/class-wpslug-admin.php:574 #: includes/class-wpslug-admin.php:574
msgid "Translation Settings" msgid "Translation Settings"
msgstr "" msgstr ""


#: includes/class-wpslug-admin.php:575 #: includes/class-wpslug-admin.php:576
msgid "Use online translation services to convert text to English slugs." msgid "Use online translation services to convert text to English slugs."
msgstr "" msgstr ""


#: includes/class-wpslug-admin.php:583 #: includes/class-wpslug-admin.php:584
msgid "Translation Service" msgid "Translation Service"
msgstr "" msgstr ""


#: includes/class-wpslug-admin.php:604 #: includes/class-wpslug-admin.php:605
msgid "Choose translation service. Useful for non-English content to generate English slugs." msgid ""
"Choose translation service. Useful for non-English content to generate "
"English slugs."
msgstr "" msgstr ""


#: includes/class-wpslug-admin.php:612 #: includes/class-wpslug-admin.php:612
msgid "Source Language" msgid "Source Language"
msgstr "" msgstr ""


#: includes/class-wpslug-admin.php:630 #: includes/class-wpslug-admin.php:631
msgid "Source language for translation. Auto-detect is recommended." msgid "Source language for translation. Auto-detect is recommended."
msgstr "" msgstr ""


@ -273,7 +267,7 @@ msgstr ""
msgid "Target Language" msgid "Target Language"
msgstr "" msgstr ""


#: includes/class-wpslug-admin.php:656 #: includes/class-wpslug-admin.php:657
msgid "Target language for translation. English is recommended for SEO." msgid "Target language for translation. English is recommended for SEO."
msgstr "" msgstr ""


@ -285,18 +279,16 @@ msgstr ""
msgid "API Key" msgid "API Key"
msgstr "" msgstr ""


#: includes/class-wpslug-admin.php:679 #: includes/class-wpslug-admin.php:679 includes/class-wpslug-admin.php:728
#: includes/class-wpslug-admin.php:728 #: includes/class-wpslug-admin.php:1268
#: includes/class-wpslug-admin.php:1297
msgid "Test API" msgid "Test API"
msgstr "" msgstr ""


#: includes/class-wpslug-admin.php:682 #: includes/class-wpslug-admin.php:683
msgid "Enter your Google Translate API key." msgid "Enter your Google Translate API key."
msgstr "" msgstr ""


#: includes/class-wpslug-admin.php:687 #: includes/class-wpslug-admin.php:687 includes/class-wpslug-admin.php:736
#: includes/class-wpslug-admin.php:736
msgid "Get API Key" msgid "Get API Key"
msgstr "" msgstr ""


@ -308,288 +300,261 @@ msgstr ""
msgid "App ID" msgid "App ID"
msgstr "" msgstr ""


#: includes/class-wpslug-admin.php:708 #: includes/class-wpslug-admin.php:709
msgid "Enter your Baidu Translate App ID." msgid "Enter your Baidu Translate App ID."
msgstr "" msgstr ""


#: includes/class-wpslug-admin.php:716 #: includes/class-wpslug-admin.php:717
msgid "Secret Key" msgid "Secret Key"
msgstr "" msgstr ""


#: includes/class-wpslug-admin.php:731 #: includes/class-wpslug-admin.php:732
msgid "Enter your Baidu Translate Secret Key." msgid "Enter your Baidu Translate Secret Key."
msgstr "" msgstr ""


#: includes/class-wpslug-admin.php:745
msgid "WPMind AI Translation"
msgstr ""

#: includes/class-wpslug-admin.php:750
msgid "WPMind is active and configured. No additional settings required."
msgstr ""

#: includes/class-wpslug-admin.php:753 #: includes/class-wpslug-admin.php:753
msgid "WPMind uses AI to translate titles to SEO-friendly slugs. It provides more accurate and context-aware translations compared to traditional translation services." msgid ""
"Optimize slugs for better search engine performance and user experience."
msgstr "" msgstr ""


#: includes/class-wpslug-admin.php:757 #: includes/class-wpslug-admin.php:761
msgid "Configure WPMind Settings"
msgstr ""

#: includes/class-wpslug-admin.php:763
msgid "WPMind plugin is not active or not configured."
msgstr ""

#: includes/class-wpslug-admin.php:766
msgid "Please install and activate the WPMind plugin to use AI-powered translation."
msgstr ""

#: includes/class-wpslug-admin.php:767
msgid "Learn more"
msgstr ""

#: includes/class-wpslug-admin.php:781
msgid "Optimize slugs for better search engine performance and user experience."
msgstr ""

#: includes/class-wpslug-admin.php:789
msgid "Enable SEO Optimization" msgid "Enable SEO Optimization"
msgstr "" msgstr ""


#: includes/class-wpslug-admin.php:804 #: includes/class-wpslug-admin.php:776
msgid "Enable SEO-friendly slug optimization" msgid "Enable SEO-friendly slug optimization"
msgstr "" msgstr ""


#: includes/class-wpslug-admin.php:810 #: includes/class-wpslug-admin.php:782
msgid "Apply SEO best practices to generated slugs." msgid "Apply SEO best practices to generated slugs."
msgstr "" msgstr ""


#: includes/class-wpslug-admin.php:818 #: includes/class-wpslug-admin.php:789
msgid "Smart Punctuation" msgid "Smart Punctuation"
msgstr "" msgstr ""


#: includes/class-wpslug-admin.php:829 #: includes/class-wpslug-admin.php:801
msgid "Intelligently handle punctuation marks" msgid "Intelligently handle punctuation marks"
msgstr "" msgstr ""


#: includes/class-wpslug-admin.php:835 #: includes/class-wpslug-admin.php:807
msgid "Convert colons, semicolons, and other punctuation to hyphens or remove them." msgid ""
"Convert colons, semicolons, and other punctuation to hyphens or remove them."
msgstr "" msgstr ""


#: includes/class-wpslug-admin.php:843 #: includes/class-wpslug-admin.php:815
msgid "Mixed Content Optimization" msgid "Mixed Content Optimization"
msgstr "" msgstr ""


#: includes/class-wpslug-admin.php:857 #: includes/class-wpslug-admin.php:829
msgid "Optimize mixed language and number content" msgid "Optimize mixed language and number content"
msgstr "" msgstr ""


#: includes/class-wpslug-admin.php:863 #: includes/class-wpslug-admin.php:835
msgid "Better handling of content mixing languages with numbers and English text." msgid ""
"Better handling of content mixing languages with numbers and English text."
msgstr "" msgstr ""


#: includes/class-wpslug-admin.php:871 #: includes/class-wpslug-admin.php:842
msgid "Remove Stop Words" msgid "Remove Stop Words"
msgstr "" msgstr ""


#: includes/class-wpslug-admin.php:883 #: includes/class-wpslug-admin.php:855
msgid "Remove common stop words from slugs" msgid "Remove common stop words from slugs"
msgstr "" msgstr ""


#: includes/class-wpslug-admin.php:889 #: includes/class-wpslug-admin.php:861
msgid "Remove words like \"the\", \"a\", \"an\", \"and\", etc. to create cleaner slugs." msgid ""
"Remove words like \"the\", \"a\", \"an\", \"and\", etc. to create cleaner "
"slugs."
msgstr "" msgstr ""


#: includes/class-wpslug-admin.php:897 #: includes/class-wpslug-admin.php:868
msgid "Maximum Words" msgid "Maximum Words"
msgstr "" msgstr ""


#: includes/class-wpslug-admin.php:908 #: includes/class-wpslug-admin.php:880
msgid "Maximum number of words to keep in slug for SEO optimization." msgid "Maximum number of words to keep in slug for SEO optimization."
msgstr "" msgstr ""


#: includes/class-wpslug-admin.php:916 #: includes/class-wpslug-admin.php:887
msgid "Stop Words List" msgid "Stop Words List"
msgstr "" msgstr ""


#: includes/class-wpslug-admin.php:926 #: includes/class-wpslug-admin.php:898
msgid "Comma-separated list of stop words to remove from slugs." msgid "Comma-separated list of stop words to remove from slugs."
msgstr "" msgstr ""


#: includes/class-wpslug-admin.php:942 #: includes/class-wpslug-admin.php:914
msgid "Configure how media file names are handled during upload." msgid "Configure how media file names are handled during upload."
msgstr "" msgstr ""


#: includes/class-wpslug-admin.php:950 #: includes/class-wpslug-admin.php:922
msgid "Media File Conversion" msgid "Media File Conversion"
msgstr "" msgstr ""


#: includes/class-wpslug-admin.php:964 #: includes/class-wpslug-admin.php:936
msgid "Disable automatic file name conversion for uploaded media" msgid "Disable automatic file name conversion for uploaded media"
msgstr "" msgstr ""


#: includes/class-wpslug-admin.php:970 #: includes/class-wpslug-admin.php:942
msgid "When checked, media files will not be converted automatically." msgid "When checked, media files will not be converted automatically."
msgstr "" msgstr ""


#: includes/class-wpslug-admin.php:978 #: includes/class-wpslug-admin.php:950
msgid "Media Conversion Mode" msgid "Media Conversion Mode"
msgstr "" msgstr ""


#: includes/class-wpslug-admin.php:988 #: includes/class-wpslug-admin.php:960 includes/class-wpslug-settings.php:544
#: includes/class-wpslug-settings.php:578
msgid "Normal Conversion (same as content)" msgid "Normal Conversion (same as content)"
msgstr "" msgstr ""


#: includes/class-wpslug-admin.php:997 #: includes/class-wpslug-admin.php:969 includes/class-wpslug-settings.php:545
#: includes/class-wpslug-settings.php:579
msgid "MD5 Hash (generates unique hash)" msgid "MD5 Hash (generates unique hash)"
msgstr "" msgstr ""


#: includes/class-wpslug-admin.php:1006 #: includes/class-wpslug-admin.php:978 includes/class-wpslug-settings.php:546
#: includes/class-wpslug-settings.php:580
msgid "No Conversion (keep original)" msgid "No Conversion (keep original)"
msgstr "" msgstr ""


#: includes/class-wpslug-admin.php:1013 #: includes/class-wpslug-admin.php:985
msgid "Choose how media file names should be processed. MD5 creates unique hashes for file names." msgid ""
"Choose how media file names should be processed. MD5 creates unique hashes "
"for file names."
msgstr "" msgstr ""


#: includes/class-wpslug-admin.php:1021 #: includes/class-wpslug-admin.php:992
msgid "Media File Prefix" msgid "Media File Prefix"
msgstr "" msgstr ""


#: includes/class-wpslug-admin.php:1030 #: includes/class-wpslug-admin.php:1002
msgid "Optional prefix to add to all media file names (e.g., \"img-\", \"file-\")." msgid ""
"Optional prefix to add to all media file names (e.g., \"img-\", \"file-\")."
msgstr "" msgstr ""


#: includes/class-wpslug-admin.php:1038 #: includes/class-wpslug-admin.php:1010
msgid "Preserve Original Extension" msgid "Preserve Original Extension"
msgstr "" msgstr ""


#: includes/class-wpslug-admin.php:1052 #: includes/class-wpslug-admin.php:1024
msgid "Always preserve the original file extension" msgid "Always preserve the original file extension"
msgstr "" msgstr ""


#: includes/class-wpslug-admin.php:1058 #: includes/class-wpslug-admin.php:1030
msgid "Ensures file extensions are kept even when using MD5 conversion." msgid "Ensures file extensions are kept even when using MD5 conversion."
msgstr "" msgstr ""


#: includes/class-wpslug-admin.php:1073 #: includes/class-wpslug-admin.php:1044
msgid "Advanced Settings" msgid "Advanced Settings"
msgstr "" msgstr ""


#: includes/class-wpslug-admin.php:1074 #: includes/class-wpslug-admin.php:1046
msgid "Advanced options and content type configuration for power users." msgid "Advanced options and content type configuration for power users."
msgstr "" msgstr ""


#: includes/class-wpslug-admin.php:1082 #: includes/class-wpslug-admin.php:1053
msgid "Content Types" msgid "Content Types"
msgstr "" msgstr ""


#: includes/class-wpslug-admin.php:1084 #: includes/class-wpslug-admin.php:1055
msgid "Post Types" msgid "Post Types"
msgstr "" msgstr ""


#: includes/class-wpslug-admin.php:1116 #: includes/class-wpslug-admin.php:1088
msgid "Select post types to apply slug conversion." msgid "Select post types to apply slug conversion."
msgstr "" msgstr ""


#: includes/class-wpslug-admin.php:1122 #: includes/class-wpslug-admin.php:1093
msgid "Taxonomies" msgid "Taxonomies"
msgstr "" msgstr ""


#: includes/class-wpslug-admin.php:1154 #: includes/class-wpslug-admin.php:1126
msgid "Select taxonomies to apply slug conversion." msgid "Select taxonomies to apply slug conversion."
msgstr "" msgstr ""


#: includes/class-wpslug-admin.php:1162 #: includes/class-wpslug-admin.php:1133
msgid "Display Options" msgid "Display Options"
msgstr "" msgstr ""


#: includes/class-wpslug-admin.php:1173 #: includes/class-wpslug-admin.php:1145
msgid "Show slug column in post and page lists for easy reference" msgid "Show slug column in post and page lists for easy reference"
msgstr "" msgstr ""


#: includes/class-wpslug-admin.php:1203 #: includes/class-wpslug-admin.php:1175
msgid "WP Slug Plugin Active" msgid "WP Slug Plugin Active"
msgstr "" msgstr ""


#: includes/class-wpslug-admin.php:1207 #: includes/class-wpslug-admin.php:1179
msgid "Your slugs are automatically converted based on your WP Slug settings." msgid "Your slugs are automatically converted based on your WP Slug settings."
msgstr "" msgstr ""


#: includes/class-wpslug-admin.php:1214 #: includes/class-wpslug-admin.php:1185
msgid "Configure WP Slug" msgid "Configure WP Slug"
msgstr "" msgstr ""


#: includes/class-wpslug-admin.php:1295 #: includes/class-wpslug-admin.php:1266
msgid "Converting..." msgid "Converting..."
msgstr "" msgstr ""


#: includes/class-wpslug-admin.php:1296 #: includes/class-wpslug-admin.php:1267
msgid "Testing..." msgid "Testing..."
msgstr "" msgstr ""


#: includes/class-wpslug-admin.php:1298 #: includes/class-wpslug-admin.php:1270
msgid "Are you sure you want to reset all settings to default values?" msgid "Are you sure you want to reset all settings to default values?"
msgstr "" msgstr ""


#: includes/class-wpslug-admin.php:1302 #: includes/class-wpslug-admin.php:1274 includes/class-wpslug-admin.php:1373
#: includes/class-wpslug-admin.php:1402
msgid "API connection successful!" msgid "API connection successful!"
msgstr "" msgstr ""


#: includes/class-wpslug-admin.php:1306 #: includes/class-wpslug-admin.php:1278 includes/class-wpslug-admin.php:1378
#: includes/class-wpslug-admin.php:1406
msgid "API connection failed. Please check your credentials." msgid "API connection failed. Please check your credentials."
msgstr "" msgstr ""


#: includes/class-wpslug-admin.php:1310 #: includes/class-wpslug-admin.php:1281 includes/class-wpslug-admin.php:1299
#: includes/class-wpslug-admin.php:1328
msgid "Please enter some text to preview." msgid "Please enter some text to preview."
msgstr "" msgstr ""


#: includes/class-wpslug-admin.php:1311 #: includes/class-wpslug-admin.php:1283 includes/class-wpslug-admin.php:1318
#: includes/class-wpslug-admin.php:1346
msgid "Conversion failed. Please check your settings." msgid "Conversion failed. Please check your settings."
msgstr "" msgstr ""


#: includes/class-wpslug-admin.php:1365 #: includes/class-wpslug-admin.php:1337
msgid "Google API key is required for testing." msgid "Google API key is required for testing."
msgstr "" msgstr ""


#: includes/class-wpslug-admin.php:1377 #: includes/class-wpslug-admin.php:1349
msgid "Both Baidu App ID and Secret Key are required for testing." msgid "Both Baidu App ID and Secret Key are required for testing."
msgstr "" msgstr ""


#: includes/class-wpslug-admin.php:1386 #: includes/class-wpslug-admin.php:1357
msgid "Invalid service selected." msgid "Invalid service selected."
msgstr "" msgstr ""


#: includes/class-wpslug-admin.php:1415 #: includes/class-wpslug-admin.php:1386
msgid "API connection failed: " msgid "API connection failed: "
msgstr "" msgstr ""


#: includes/class-wpslug-admin.php:1440 #: includes/class-wpslug-admin.php:1412
msgid "Disable automatic slug conversion for this post" msgid "Disable automatic slug conversion for this post"
msgstr "" msgstr ""


#: includes/class-wpslug-admin.php:1457 #: includes/class-wpslug-admin.php:1428
#, php-format #, php-format
msgid "Convert Slugs (%s)" msgid "Convert Slugs (%s)"
msgstr "" msgstr ""


#: includes/class-wpslug-admin.php:1511 #: includes/class-wpslug-admin.php:1482
#, php-format #, php-format
msgid "Successfully converted %d slug(s)." msgid "Successfully converted %d slug(s)."
msgstr "" msgstr ""


#: includes/class-wpslug-core.php:363 #: includes/class-wpslug-core.php:327
msgid "N/A" msgid "N/A"
msgstr "" msgstr ""


#: includes/class-wpslug-core.php:378 #: includes/class-wpslug-core.php:342
msgid "Error" msgid "Error"
msgstr "" msgstr ""


@ -597,249 +562,248 @@ msgstr ""
msgid "Chinese Pinyin Conversion" msgid "Chinese Pinyin Conversion"
msgstr "" msgstr ""


#: includes/class-wpslug-settings.php:246 #: includes/class-wpslug-settings.php:243
msgid "Semantic Pinyin (WPMind AI)"
msgstr ""

#: includes/class-wpslug-settings.php:248
msgid "Semantic Pinyin (Requires WPMind)"
msgstr ""

#: includes/class-wpslug-settings.php:251
msgid "Foreign Language Transliteration" msgid "Foreign Language Transliteration"
msgstr "" msgstr ""


#: includes/class-wpslug-settings.php:255 #: includes/class-wpslug-settings.php:246
msgid "Multi-language Translation" msgid "Multi-language Translation"
msgstr "" msgstr ""


#: includes/class-wpslug-settings.php:263 #: includes/class-wpslug-settings.php:253
msgid "Basic Character Mapping" msgid "Basic Character Mapping"
msgstr "" msgstr ""


#: includes/class-wpslug-settings.php:267 #: includes/class-wpslug-settings.php:257
msgid "iconv Transliteration" msgid "iconv Transliteration"
msgstr "" msgstr ""


#: includes/class-wpslug-settings.php:271 #: includes/class-wpslug-settings.php:261
msgid "PHP Intl Extension" msgid "PHP Intl Extension"
msgstr "" msgstr ""


#: includes/class-wpslug-settings.php:280 #: includes/class-wpslug-settings.php:270
msgid "None" msgid "None"
msgstr "" msgstr ""


#: includes/class-wpslug-settings.php:281 #: includes/class-wpslug-settings.php:271
msgid "Google Translate" msgid "Google Translate"
msgstr "" msgstr ""


#: includes/class-wpslug-settings.php:282 #: includes/class-wpslug-settings.php:272
msgid "Baidu Translate" msgid "Baidu Translate"
msgstr "" msgstr ""


#: includes/class-wpslug-settings.php:289 #: includes/class-wpslug-settings.php:279
msgid "WPMind AI (Recommended)"
msgstr ""

#: includes/class-wpslug-settings.php:294
msgid "WPMind AI (Not Configured)"
msgstr ""

#: includes/class-wpslug-settings.php:303
msgid "Auto Detect" msgid "Auto Detect"
msgstr "" msgstr ""


#: includes/class-wpslug-settings.php:304 #: includes/class-wpslug-settings.php:280
msgid "Chinese (Simplified)" msgid "Chinese (Simplified)"
msgstr "" msgstr ""


#: includes/class-wpslug-settings.php:305 #: includes/class-wpslug-settings.php:281
msgid "Chinese (Traditional)" msgid "Chinese (Traditional)"
msgstr "" msgstr ""


#: includes/class-wpslug-settings.php:306 #: includes/class-wpslug-settings.php:282
msgid "English" msgid "English"
msgstr "" msgstr ""


#: includes/class-wpslug-settings.php:307 #: includes/class-wpslug-settings.php:283
msgid "Spanish" msgid "Spanish"
msgstr "" msgstr ""


#: includes/class-wpslug-settings.php:308 #: includes/class-wpslug-settings.php:284
msgid "French" msgid "French"
msgstr "" msgstr ""


#: includes/class-wpslug-settings.php:309 #: includes/class-wpslug-settings.php:285
msgid "German" msgid "German"
msgstr "" msgstr ""


#: includes/class-wpslug-settings.php:310 #: includes/class-wpslug-settings.php:286
msgid "Japanese" msgid "Japanese"
msgstr "" msgstr ""


#: includes/class-wpslug-settings.php:311 #: includes/class-wpslug-settings.php:287
msgid "Korean" msgid "Korean"
msgstr "" msgstr ""


#: includes/class-wpslug-settings.php:312 #: includes/class-wpslug-settings.php:288
msgid "Russian" msgid "Russian"
msgstr "" msgstr ""


#: includes/class-wpslug-settings.php:313 #: includes/class-wpslug-settings.php:289
msgid "Arabic" msgid "Arabic"
msgstr "" msgstr ""


#: includes/class-wpslug-settings.php:314 #: includes/class-wpslug-settings.php:290
msgid "Italian" msgid "Italian"
msgstr "" msgstr ""


#: includes/class-wpslug-settings.php:315 #: includes/class-wpslug-settings.php:291
msgid "Portuguese" msgid "Portuguese"
msgstr "" msgstr ""


#: includes/class-wpslug-settings.php:316 #: includes/class-wpslug-settings.php:292
msgid "Dutch" msgid "Dutch"
msgstr "" msgstr ""


#: includes/class-wpslug-settings.php:317 #: includes/class-wpslug-settings.php:293
msgid "Polish" msgid "Polish"
msgstr "" msgstr ""


#: includes/class-wpslug-settings.php:318 #: includes/class-wpslug-settings.php:294
msgid "Turkish" msgid "Turkish"
msgstr "" msgstr ""


#: includes/class-wpslug-settings.php:319 #: includes/class-wpslug-settings.php:295
msgid "Swedish" msgid "Swedish"
msgstr "" msgstr ""


#: includes/class-wpslug-settings.php:320 #: includes/class-wpslug-settings.php:296
msgid "Danish" msgid "Danish"
msgstr "" msgstr ""


#: includes/class-wpslug-settings.php:321 #: includes/class-wpslug-settings.php:297
msgid "Norwegian" msgid "Norwegian"
msgstr "" msgstr ""


#: includes/class-wpslug-settings.php:322 #: includes/class-wpslug-settings.php:298
msgid "Finnish" msgid "Finnish"
msgstr "" msgstr ""


#: includes/class-wpslug-settings.php:323 #: includes/class-wpslug-settings.php:299
msgid "Czech" msgid "Czech"
msgstr "" msgstr ""


#: includes/class-wpslug-settings.php:324 #: includes/class-wpslug-settings.php:300
msgid "Hungarian" msgid "Hungarian"
msgstr "" msgstr ""


#: includes/class-wpslug-settings.php:325 #: includes/class-wpslug-settings.php:301
msgid "Romanian" msgid "Romanian"
msgstr "" msgstr ""


#: includes/class-wpslug-settings.php:326 #: includes/class-wpslug-settings.php:302
msgid "Bulgarian" msgid "Bulgarian"
msgstr "" msgstr ""


#: includes/class-wpslug-settings.php:327 #: includes/class-wpslug-settings.php:303
msgid "Croatian" msgid "Croatian"
msgstr "" msgstr ""


#: includes/class-wpslug-settings.php:328 #: includes/class-wpslug-settings.php:304
msgid "Slovak" msgid "Slovak"
msgstr "" msgstr ""


#: includes/class-wpslug-settings.php:329 #: includes/class-wpslug-settings.php:305
msgid "Slovenian" msgid "Slovenian"
msgstr "" msgstr ""


#: includes/class-wpslug-settings.php:330 #: includes/class-wpslug-settings.php:306
msgid "Estonian" msgid "Estonian"
msgstr "" msgstr ""


#: includes/class-wpslug-settings.php:331 #: includes/class-wpslug-settings.php:307
msgid "Latvian" msgid "Latvian"
msgstr "" msgstr ""


#: includes/class-wpslug-settings.php:332 #: includes/class-wpslug-settings.php:308
msgid "Lithuanian" msgid "Lithuanian"
msgstr "" msgstr ""


#: includes/class-wpslug-settings.php:333 #: includes/class-wpslug-settings.php:309
msgid "Maltese" msgid "Maltese"
msgstr "" msgstr ""


#: includes/class-wpslug-settings.php:334 #: includes/class-wpslug-settings.php:310
msgid "Greek" msgid "Greek"
msgstr "" msgstr ""


#: includes/class-wpslug-settings.php:335 #: includes/class-wpslug-settings.php:311
msgid "Welsh" msgid "Welsh"
msgstr "" msgstr ""


#: includes/class-wpslug-settings.php:421 #: includes/class-wpslug-settings.php:387
msgid "Invalid import data format." msgid "Invalid import data format."
msgstr "" msgstr ""


#: includes/class-wpslug-settings.php:434 #: includes/class-wpslug-settings.php:400
msgid "Failed to update options." msgid "Failed to update options."
msgstr "" msgstr ""


#: includes/class-wpslug-settings.php:702 #: includes/class-wpslug-settings.php:669
#: includes/class-wpslug-validator.php:155 #: includes/class-wpslug-validator.php:154
msgid "Google API key is required for Google Translate service." msgid "Google API key is required for Google Translate service."
msgstr "" msgstr ""


#: includes/class-wpslug-settings.php:712 #: includes/class-wpslug-settings.php:679
#: includes/class-wpslug-validator.php:159 #: includes/class-wpslug-validator.php:158
msgid "Baidu App ID and Secret Key are required for Baidu Translate service." msgid "Baidu App ID and Secret Key are required for Baidu Translate service."
msgstr "" msgstr ""


#: includes/class-wpslug-settings.php:721 #: includes/class-wpslug-settings.php:687
#: includes/class-wpslug-validator.php:186 #: includes/class-wpslug-validator.php:176
msgid "PHP 7.0 or higher is required." msgid "PHP 7.0 or higher is required."
msgstr "" msgstr ""


#: includes/class-wpslug-settings.php:724 #: includes/class-wpslug-settings.php:691
#: includes/class-wpslug-validator.php:190 #: includes/class-wpslug-validator.php:180
msgid "WordPress 5.0 or higher is required." msgid "WordPress 5.0 or higher is required."
msgstr "" msgstr ""


#: includes/class-wpslug-settings.php:730 #: includes/class-wpslug-settings.php:696
#: includes/class-wpslug-validator.php:194 #: includes/class-wpslug-validator.php:184
msgid "PHP mbstring extension is required." msgid "PHP mbstring extension is required."
msgstr "" msgstr ""


#: includes/class-wpslug-settings.php:733 #: includes/class-wpslug-settings.php:699
#: includes/class-wpslug-validator.php:198 #: includes/class-wpslug-validator.php:188
msgid "PHP JSON extension is required." msgid "PHP JSON extension is required."
msgstr "" msgstr ""


#: includes/class-wpslug-validator.php:165 #: wpslug.php:63
msgid "WPMind plugin is not installed."
msgstr ""

#: includes/class-wpslug-validator.php:167
msgid "WPMind is not configured. Please configure it in WPMind settings."
msgstr ""

#: wpslug.php:67
msgid "WP Slug requires PHP 7.0 or higher. Please upgrade your PHP version." msgid "WP Slug requires PHP 7.0 or higher. Please upgrade your PHP version."
msgstr "" msgstr ""


#: wpslug.php:76 #: wpslug.php:72
msgid "WP Slug requires WordPress 5.0 or higher. Please upgrade your WordPress version." msgid ""
"WP Slug requires WordPress 5.0 or higher. Please upgrade your WordPress "
"version."
msgstr "" msgstr ""


#: wpslug.php:130 #: wpslug.php:125
msgid "WP Slug plugin requirements not met. Please check your PHP and WordPress versions." msgid ""
"WP Slug plugin requirements not met. Please check your PHP and WordPress "
"versions."
msgstr "" msgstr ""


#: wpslug.php:131 #: wpslug.php:126 wpslug.php:146
#: wpslug.php:151
msgid "Plugin Activation Error" msgid "Plugin Activation Error"
msgstr "" msgstr ""


#: wpslug.php:150 #: wpslug.php:145
msgid "An error occurred during plugin activation. Please check your server logs." msgid ""
"An error occurred during plugin activation. Please check your server logs."
msgstr ""

#. Plugin Name of the plugin/theme
msgid "WPSlug"
msgstr ""

#. Plugin URI of the plugin/theme
#. Author URI of the plugin/theme
msgid "https://wpslug.com"
msgstr ""

#. Description of the plugin/theme
msgid ""
"Advanced slug management plugin with Chinese Pinyin support and SEO "
"optimization."
msgstr ""

#. Author of the plugin/theme
msgid "WPSlug.com"
msgstr "" msgstr ""

View file

@ -2,11 +2,11 @@


/* /*
Plugin Name: WPSlug Plugin Name: WPSlug
Plugin URI: https://wpcy.com/slug Plugin URI: https://wpslug.com
Description: Advanced slug management plugin with Chinese Pinyin support and SEO optimization. Description: Advanced slug management plugin with Chinese Pinyin support and SEO optimization.
Version: 1.1.1 Version: 1.0.7
Author: WPSlug Author: WPSlug.com
Author URI: https://wpcy.com/slug Author URI: https://wpslug.com
License: GPL2 License: GPL2
Text Domain: wpslug Text Domain: wpslug
Domain Path: /languages Domain Path: /languages
@ -19,7 +19,7 @@ if (!defined("ABSPATH")) {
exit(); exit();
} }


define("WPSLUG_VERSION", "1.1.1"); define("WPSLUG_VERSION", "1.0.7");
define("WPSLUG_PLUGIN_DIR", plugin_dir_path(__FILE__)); define("WPSLUG_PLUGIN_DIR", plugin_dir_path(__FILE__));
define("WPSLUG_PLUGIN_URL", plugin_dir_url(__FILE__)); define("WPSLUG_PLUGIN_URL", plugin_dir_url(__FILE__));
define("WPSLUG_PLUGIN_BASENAME", plugin_basename(__FILE__)); define("WPSLUG_PLUGIN_BASENAME", plugin_basename(__FILE__));
@ -56,7 +56,7 @@ class WPSlug
$this->loadDependencies(); $this->loadDependencies();
$this->loadTextdomain(); $this->loadTextdomain();
$this->core = new WPSlug_Core(); $this->core = new WPSlug_Core();
new WenPai_Updater( WPSLUG_PLUGIN_BASENAME, WPSLUG_VERSION ); new WPSlug_Updater(WPSLUG_PLUGIN_BASENAME, WPSLUG_VERSION);
} }


private function checkRequirements() private function checkRequirements()
@ -92,7 +92,7 @@ class WPSlug
require_once WPSLUG_PLUGIN_DIR . "includes/class-wpslug-translator.php"; require_once WPSLUG_PLUGIN_DIR . "includes/class-wpslug-translator.php";
require_once WPSLUG_PLUGIN_DIR . "includes/class-wpslug-converter.php"; require_once WPSLUG_PLUGIN_DIR . "includes/class-wpslug-converter.php";
require_once WPSLUG_PLUGIN_DIR . "includes/class-wpslug-core.php"; require_once WPSLUG_PLUGIN_DIR . "includes/class-wpslug-core.php";
require_once WPSLUG_PLUGIN_DIR . "includes/class-wenpai-updater.php"; require_once WPSLUG_PLUGIN_DIR . "includes/class-wpslug-updater.php";


if (is_admin()) { if (is_admin()) {
require_once WPSLUG_PLUGIN_DIR . "includes/class-wpslug-admin.php"; require_once WPSLUG_PLUGIN_DIR . "includes/class-wpslug-admin.php";